【问题标题】:Use previous value from previous rows for nulls in SQL使用前一行中的前一个值作为 SQL 中的空值
【发布时间】:2018-11-16 16:53:20
【问题描述】:

我正在尝试用之前的值填充所有空值,但前提是字段帐户相同。我了解到我的表需要有一个主键。目前我的桌子上没有它,是否可以使用表格的行数创建一个,请参见下表:

CREATE TABLE test (ACCOUNT_NO INT, RATE INT, DATE_L DATE, ROWCOUNT INT);    
   INSERT INTO test VALUES (1, 3, '2017-12-31',1);
   INSERT INTO test VALUES (1, NULL, '2018-01-31',2);
   INSERT INTO test VALUES (3, 5, '2017-12-31',3);
   INSERT INTO test VALUES (3, NULL, '2018-01-31',4);
   INSERT INTO test VALUES (3, NULL, '2018-02-28',5);
   INSERT INTO test VALUES (6, 2, '2018-03-04',6);
   INSERT INTO test VALUES (6, NULL, '2018-03-04',7);
   INSERT INTO test VALUES (6, 5, '2018-03-04',8);
   INSERT INTO test VALUES (6, NULL, '2018-03-04',9);
   INSERT INTO test VALUES (6, NULL, '2018-03-04',10);

所以表格看起来像这样:

|ACCOUNT_NO|RATE|DATE_L    |RowCount|
|1         |3   |2017-12-31|1       |
|1         |NULL|2018-01-31|2       |
|3         |5   |2017-12-31|3       |
|3         |NULL|2018-01-31|4       |
|3         |NULL|2018-02-28|5       |
|6         |2   |2018-03-04|6       |
|6         |NULL|2018-03-04|7       |
|6         |5   |2018-03-04|8       |
|6         |NULL|2018-03-04|9       |
|6         |NULL|2018-03-04|10      |

我希望它看起来像这样:

|ACCOUNT_NO|RATE|DATE_L    |RowCount|
|1         |3   |2017-12-31|1       |
|1         |3   |2018-01-31|2       |
|3         |5   |2017-12-31|3       |
|3         |5   |2018-01-31|4       |
|3         |5   |2018-02-28|5       |
|6         |2   |2018-03-04|6       |
|6         |2   |2018-03-04|7       |
|6         |5   |2018-03-04|8       |
|6         |5   |2018-03-04|9       |
|6         |5   |2018-03-04|10      |

欢迎任何帮助,并在此先感谢您。

【问题讨论】:

  • 您是在尝试选择还是更新?
  • SQL 表代表 无序 集。除非数据中的一列指定了排序,否则没有先前的值。
  • 表中有主键吗?或日期时间列?没有它,我们真的无法定义什么是前一个,什么是下一个。数据以无序的方式存储。
  • 请回答上述 cmets 中提出的问题。你的问题是不完整的。
  • 你没有PK。没有一个,这个问题基本上是无法解决的。

标签: mysql sql


【解决方案1】:

正如稍后编辑的问题,ROWCOUNT 列用于定义“上一行/最后一行”。基本前提是较低的ROWCOUNT 值意味着“较旧/上一个”行。

然后您可以使用Correlated Subquery 和条件CASE .. WHEN 表达式来确定同一ACCOUNT_NO 的最后一个NON NULL 值:

查询

SELECT
  t1.ACCOUNT_NO, 
  CASE WHEN t1.RATE IS NULL 
         THEN (SELECT t2.RATE 
               FROM test AS t2 
               WHERE t2.ROWCOUNT < t1.ROWCOUNT AND 
                     t2.ACCOUNT_NO = t1.ACCOUNT_NO AND 
                     t2.RATE IS NOT NULL 
               ORDER BY t2.ROWCOUNT DESC 
               LIMIT 1)
       ELSE t1.RATE
  END AS RATE, 
  t1.DATE_L, 
  t1.ROWCOUNT 
FROM test AS t1;

结果

| ACCOUNT_NO | DATE_L     | ROWCOUNT | RATE |
| ---------- | ---------- | -------- | ---- |
| 1          | 2017-12-31 | 1        | 3    |
| 1          | 2018-01-31 | 2        | 3    |
| 3          | 2017-12-31 | 3        | 5    |
| 3          | 2018-01-31 | 4        | 5    |
| 3          | 2018-02-28 | 5        | 5    |
| 6          | 2018-03-04 | 6        | 2    |
| 6          | 2018-03-04 | 7        | 2    |
| 6          | 2018-03-04 | 8        | 5    |
| 6          | 2018-03-04 | 9        | 5    |
| 6          | 2018-03-04 | 10       | 5    |

View on DB Fiddle

【讨论】:

  • 这个方案不仅假设定义了一个主键,而且还假设它是一个自增字段。
  • @Shadow 不一定;此解决方案可以处理 PK 中的空白。 PK 要求是唯一的(可能不一定是自动递增的)。基本前提是较低的id 值意味着“较旧/上一个”行。
  • @MadhurBhaiya 我可以使用 Date_L 作为我的主键吗?
  • @SIM2000 如上面 cmets 中所述,您可以在我的查询中将 id 替换为 RowCount。它会为你工作。
  • @MadhurBhaiya 我已经用 RowCount 替换了 id,但我仍然收到语法错误“接近 LIMIT”。来回抱歉,我是 SQL 新手。请协助。谢谢。
【解决方案2】:

您的问题似乎不是基于以前的值,而是基于相同account_no的非NULL值。

update test t join
       (select account_no, max(rate) as max_rate
        from test t
        group by account_no
       ) a
       using (account_no)
    set t.rate = a.max_rate
    where t.rate is null;

【讨论】:

  • 查看account no=6 行!
  • @GordonLinoff 你能用 SELECT 语句代替更新吗?
【解决方案3】:

使用下面的简单查询。你可以得到预期的结果。

UPDATE test AS t1
INNER JOIN 
    (SELECT ACCOUNT_NO, RATE FROM test WHERE RATE !='' GROUP BY ACCOUNT_NO) AS t2 ON t1.ACCOUNT_NO=t2.ACCOUNT_NO
SET t1.RATE=t2.RATE
WHERE t1.RATE IS NULL OR t1.RATE = ''

【讨论】:

  • 你能用 SELECT 代替 UPDATE 吗?
猜你喜欢
  • 1970-01-01
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-09
相关资源
最近更新 更多