2016-06-29 14 views
5

Mam tabeli, która wygląda następująco:TSQL - Wypełnianie wartości powyżej i poniżej wpisu poprzez odniesienie innych kolumn

enter image description here

ten może być odtworzony z poniższego kodu:

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); 

I trzeba wypełnić kolumnę EMPNO.

Gdy 3 kolumny są takie same: WORKNO, RELEASED, PRODUCT, mam do czynienia z indywidualnym grupowaniem, a mój zbiór danych składa się z tych grupowań.

W ramach tego grupowania, jeśli EMPNO ma wartość null, najpierw musi zostać wypełniony przez następny EMPNO w dół, który nie jest zerowy (może to być kilka wpisów w dół). Kolejne obniżenie EMPNO określa numer OPSEQ. Jeśli nie ma EMPNO, który nie jest null w dalszej części grupowania (na przykład dwa puste wpisy na końcu), to musi być wypełniony ostatnim EMPNO powyżej, który nie jest pusty.

tabela powinna wyglądać następująco:

enter image description here

przeprosiny za brak prób kod na mojej stronie. Nie jestem pewien, od czego zacząć od tego. Wszelkie wskazówki w ogóle byłyby bardzo mile widziane.

+0

Jaką wersję serwera sql? – mxix

+0

SQL Server 2012 –

+0

Masz OPSEQ 50 zakodowany jako 698, ale zgodnie z Twoimi wymaganiami zostanie ustawiony na 345. Musisz nieco dostosować swoje wymagania. To powinno być łatwe do osiągnięcia, jeśli uda ci się wypracować ten szczegół. –

Odpowiedz

4

Istnieje wiele sposobów rozwiązania tego problemu. Jednym z nich jest APPLY.

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 
+0

jak to zrobić, aby upewnić się, że resetuje każde nowe zgrupowanie WRKNO, PRODUKTU, ZWOLNIONE? W powyższych danych pokazuję tylko jedną taką grupę. –

+1

@ ColinO'Brien Przepraszam za to, że =) po prostu dodaj to jako klucz łączący .. Zmieniono. – mxix

1

Poniższy kod może być pomocny.

Pierwszy aktualizacja będzie zapełnić EmpNo używając obok NOT NULL EmpNo

Second aktualizacji będzie wypełnić pozostałą EmpNo stosując poprzedni not null EmpNo

Korzystanie dwie aktualizacje w tym scenariuszu zmniejszy IO w porównaniu ze stosowaniem pojedynczego zapytania.

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