TSQL - 通过引用其他列来填充条目上方和下方的值

时间:2016-06-29 12:29:36

标签: sql sql-server tsql sql-server-2012

我有一张表格如下:

enter image description here

可以从以下代码重新创建:

CREATE TABLE dbo.EmpnoProblem
(
DATE date NULL,
WORKNO nvarchar(50) NULL,
OPSEQ int NULL,
RELEASED nchar(10) NULL,
PRODUCT nvarchar(50) NULL,
EMPNO nvarchar(50) NULL
) ;

INSERT INTO [dbo].[EmpnoProblem] (DATE, WORKNO, OPSEQ, RELEASED, PRODUCT, EMPNO)
VALUES ('2016-06-16', '12345', 10, '10', '5454ABC', NULL);
INSERT INTO [dbo].[EmpnoProblem] (DATE, WORKNO, OPSEQ, RELEASED, PRODUCT, EMPNO)
VALUES ('2016-06-16', '12345', 20, '10', '5454ABC', NULL);
INSERT INTO [dbo].[EmpnoProblem] (DATE, WORKNO, OPSEQ, RELEASED, PRODUCT, EMPNO)
VALUES ('2016-06-16', '12345', 30, '10', '5454ABC', '345');
INSERT INTO [dbo].[EmpnoProblem] (DATE, WORKNO, OPSEQ, RELEASED, PRODUCT, EMPNO)
VALUES ('2016-06-16', '12345', 40, '10', '5454ABC', '345');
INSERT INTO [dbo].[EmpnoProblem] (DATE, WORKNO, OPSEQ, RELEASED, PRODUCT, EMPNO)
VALUES ('2016-06-16', '12345', 50, '10', '5454ABC', NULL);
INSERT INTO [dbo].[EmpnoProblem] (DATE, WORKNO, OPSEQ, RELEASED, PRODUCT, EMPNO)
VALUES ('2016-06-16', '12345', 60, '10', '5454ABC', NULL);
INSERT INTO [dbo].[EmpnoProblem] (DATE, WORKNO, OPSEQ, RELEASED, PRODUCT, EMPNO)
VALUES ('2016-06-16', '12345', 70, '10', '5454ABC', '698');
INSERT INTO [dbo].[EmpnoProblem] (DATE, WORKNO, OPSEQ, RELEASED, PRODUCT, EMPNO)
VALUES ('2016-06-16', '12345', 80, '10', '5454ABC', NULL);
INSERT INTO [dbo].[EmpnoProblem] (DATE, WORKNO, OPSEQ, RELEASED, PRODUCT, EMPNO)
VALUES ('2016-06-16', '12345', 90, '10', '5454ABC', NULL);

我需要填充EMPNO列。

当3列相同时:WORKNO,RELEASED,PRODUCT,我正在处理单个分组,我的数据集由这些分组组成。

在此分组中,如果EMPNO为空,则首先需要由下一个非空的EMPNO填充(这可能是几个条目)。下一个EMPNO下降由OPSEQ编号决定。如果在分组中没有进一步向下的EMPNO(例如末尾的两个空条目),那么它需要由它上面的最后一个非空的EMPNO填充。

该表应如下所示:

enter image description here

为我的代码尝试缺乏代码而道歉。我不知道从哪里开始。任何指针都将非常感激。

2 个答案:

答案 0 :(得分:4)

有多种方法可以解决这个问题。一个是申请。

select 
    a.*,
    COALESCE(a.EMPNO,next_NONEMPTY_EMPNO.EMPNO,prev_NONEMPTY_EMPNO.EMPNO) EMPNO_Fixed
from #EmpnoProblem a
OUTER APPLY (
    select TOP 1
        EMPNO
    from #EmpnoProblem b
    where
        EMPNO is not null and
        a.WORKNO = b.WORKNO and
        a.RELEASED = b.RELEASED and
        a.PRODUCT = b.PRODUCT and
        b.OPSEQ > a.OPSEQ
    order by OPSEQ ASC
) next_NONEMPTY_EMPNO
OUTER APPLY (
    select TOP 1
        EMPNO
    from #EmpnoProblem b
    where
        EMPNO is not null and
        a.WORKNO = b.WORKNO and
        a.RELEASED = b.RELEASED and
        a.PRODUCT = b.PRODUCT and
        b.OPSEQ < a.OPSEQ
    order by OPSEQ DESC
) prev_NONEMPTY_EMPNO

答案 1 :(得分:1)

下面的代码可能会有所帮助。

第一次更新将使用next not null EMPNO填充EMPNO

第二次更新将使用之前的非空EMPNO填充剩余的EMPNO

与使用单个查询相比,在此方案中使用两个更新将减少IO。

UPDATE Dest
SET Dest.EMPNO=NewVal.EMPNO
FROM EmpnoProblem AS Dest
CROSS APPLY (SELECT TOP 1 Src.EMPNO FROM  EmpnoProblem AS Src WHERE Dest.WORKNO=Src.WORKNO AND Dest.RELEASED=Src.RELEASED AND Dest.PRODUCT=Src.PRODUCT AND Dest.OPSEQ<Src.OPSEQ AND Src.EMPNO IS NOT NULL ORDER BY Src.OPSEQ ASC) AS NewVal
WHERE Dest.EMPNO IS NULL;


UPDATE Dest
SET Dest.EMPNO=NewVal.EMPNO
FROM EmpnoProblem AS Dest
CROSS APPLY (SELECT TOP 1 Src.EMPNO FROM  EmpnoProblem AS Src WHERE Dest.WORKNO=Src.WORKNO AND Dest.RELEASED=Src.RELEASED AND Dest.PRODUCT=Src.PRODUCT AND Dest.OPSEQ>Src.OPSEQ AND Src.EMPNO IS NOT NULL ORDER BY Src.OPSEQ DESC) AS NewVal
WHERE Dest.EMPNO IS NULL;


SELECT *
FROM  dbo.EmpnoProblem
ORDER BY WORKNO,RELEASED,PRODUCT,OPSEQ