首页 > 解决方案 > 将空值下移到 SQL Server 中的下一行

问题描述

我有这张桌子

call_date    cust_code  order_id
   2020-06-20   A001       s001 
   2020-06-21   A001       s002 
   2020-06-22   A001       NULL 
   2020-06-23   A001       s003 
   2020-06-24   A001       s004 
   2020-06-25   A001       NULL 
   2020-06-26   A001       s005 

我想首先检查接下来的 3 条记录,如果三个记录中的任何记录不为 null,然后将 null 值与下一个 null 值交换,反之亦然,如下所示:

   call_date    cust_code  order_id
   2020-06-20   A001       s001 
   2020-06-21   A001       s002 
   2020-06-22   A001       s003
   2020-06-23   A001       s004 
   2020-06-24   A001       s005 
   2020-06-25   A001       NULL 
   2020-06-26   A001       NULL

我做了这个

update effective set order_id=ISNULL(order_id,(select Top 1 e2.order_id 
from effective e2 where e2.call_date>e1.call_date
AND e2.order_id IS NOT NULL)
) 
FROM effective e1

得到了这个:

call_date    cust_code  order_id
   2020-06-20   A001       s001 
   2020-06-21   A001       s002 
   2020-06-22   A001       s003 
   2020-06-23   A001       s003 
   2020-06-24   A001       s004 
   2020-06-25   A001       s005
   2020-06-26   A001       s005 

有人可以帮助我解决这个问题吗?

标签: sql-serverazure-sql-database

解决方案


要么我理解 qrong 的问题,要么可能有非常简单的解决方法。我刚刚创建了以下查询, ehich 一方面使用 ctes 获取所有订单,另一方面获取所有具有设置 order_id 的订单。接下来我在两个 ctes 之间执行左连接 - 结果看起来像你试图实现的......

DECLARE @t TABLE(
call_date date,
cust_code nvarchar(10),
order_id nvarchar(10)
);

INSERT INTO @t VALUES
('2020-06-20', 'A001', 's001'), 
('2020-06-21', 'A001', 's002'), 
('2020-06-22', 'A001', NULL), 
('2020-06-23', 'A001', 's003'), 
('2020-06-24', 'A001', 's004'), 
('2020-06-25', 'A001', NULL), 
('2020-06-26', 'A001', 's005');

WITH cteBase AS(
SELECT *, ROW_NUMBER() OVER (PARTITION BY cust_code ORDER BY call_date) rn
  FROM @t t
),
cteNotNULL AS(
SELECT *, ROW_NUMBER() OVER (PARTITION BY cust_code ORDER BY call_date) rn
  FROM @t t
  WHERE order_id IS NOT NULL
)
SELECT b.call_date, b.cust_code, n.order_id
  FROM cteBase b
  LEFT JOIN cteNotNULL n ON n.cust_code = b.cust_code AND n.rn = b.rn

推荐阅读