Как использовать функцию SQL LAG с условием - PullRequest
1 голос
/ 01 октября 2019

У меня есть таблица в виде следующих строк:

here you have a problem illustrator

tipoProtocolo numeroProtocolo dataReferencia dataAssinatura dataVencimento
------------- --------------- -------------- -------------- --------------
1             47676           NULL           20150112       20151231
1             47676           20151231       20150209       NULL
1             47676           NULL           20150224       NULL
1             47676           NULL           20151005       NULL
1             47676           NULL           20151021       NULL
1             47676           NULL           20151026       NULL
1             47676           NULL           20151120       NULL

Я реализовал фрагмент кода, который получает значение из столбца dataVencimento (предыдущая строка)в столбец dataRefencia (красная стрелка на изображении). Однако я хотел бы проверить, равен ли NULL столбец dataVencimento (из предыдущей строки). Если это условие истинно, мне нужно скопировать значение из столбца dataReferencia из предыдущей строки (синяя стрелка на изображении).

SELECT tipoProtocolo,
        numeroProtocolo,
            LAG(dataVencimento, 1 ) OVER(
            PARTITION BY numeroProtocolo, tipoProtocolo
            ORDER BY dataAssinatura
            ) dataReferencia,
            dataAssinatura, 
            dataVencimento
FROM cte_ContratoAditivo 

Вот мой код SQL:

SELECT tipoProtocolo, numeroProtocolo,
        LAG(dataVencimento, 1) OVER(
        PARTITION BY numeroProtocolo, tipoProtocolo
        ORDER BY dataAssinatura
        ) dataReferencia,
         dataAssinatura, dataVencimento
FROM cte_ContratoAditivo

Ответы [ 2 ]

1 голос
/ 01 октября 2019

То, что вы хотите, это lag(ignore nulls). К сожалению, SQL Server не поддерживает это.

Если даты увеличиваются, вы можете использовать совокупный максимум:

select . . .,
       max(dataVencimento) over (
            partition by numeroProtocolo, tipoProtocolo
            order by dataAssinatura
            rows between unbounded preceding and 1 preceding
        ) as dataReferencia

Если это не так, вы можете использовать два уровня:агрегация:

select ca.*,
       max(dataVencimento) over (
            partition by numeroProtocolo, tipoProtocolo
            order by dataAssinatura
      ) as dataReferencia
from (select ca.*,
             count(dataVencimento) over (
                partition by numeroProtocolo, tipoProtocolo
                order by dataAssinatura
               ) as grouping
      from cte_ContratoAditivo ca
     ) ca;

Подзапрос подсчитывает количество допустимых значений. Это действительно для присвоения номера группы строкам. Внешний запрос затем распространяет значение по всей группе.

0 голосов
/ 01 октября 2019

Когда ОП ответил, я пошел с буквальным и угаданным ответом. Первый буквальный ответ;если предыдущий ряд равен NULL, используйте тот, что предыдущий:

WITH VTE AS (
    SELECT *    
    FROM (VALUES(1,47676,CONVERT(date,NULL),CONVERT(date,'20150112'),CONVERT(date,'20151231')),
                (1,47676,CONVERT(date,'20151231'),CONVERT(date,'20150209'),CONVERT(date,NULL)),
                (1,47676,CONVERT(date,NULL),CONVERT(date,'20150224'),CONVERT(date,NULL)),
                (1,47676,CONVERT(date,NULL),CONVERT(date,'20151005'),CONVERT(date,NULL)),
                (1,47676,CONVERT(date,NULL),CONVERT(date,'20151021'),CONVERT(date,NULL)),
                (1,47676,CONVERT(date,NULL),CONVERT(date,'20151026'),CONVERT(date,NULL)),
                (1,47676,CONVERT(date,NULL),CONVERT(date,'20151120'),CONVERT(date,NULL))) V(tipoProtocolo,numeroProtocolo,dataReferencia,dataAssinatura,dataVencimento)),
CTE AS(
    SELECT V.tipoProtocolo,
           V.numeroProtocolo,
           V.dataReferencia,
           V.dataAssinatura,
           V.dataVencimento,
           LAG(dataVencimento) OVER (PARTITION BY numeroProtocolo, tipoProtocolo ORDER BY dataAssinatura) AS dataReferencia1,
           LAG(dataVencimento,2) OVER (PARTITION BY numeroProtocolo, tipoProtocolo ORDER BY dataAssinatura) AS dataReferencia2
    FROM VTE V)
SELECT C.tipoProtocolo,
       C.numeroProtocolo,
       C.dataReferencia,
       C.dataAssinatura,
       C.dataVencimento,
       ISNULL(C.dataReferencia1,C.dataReferencia2) AS dataReferencia
FROM CTE C;

Другой - это то, что, как я подозреваю, означает OP действительно , и что они хотят, чтобы последний не- NULL значение. Если это так, то это «классическая» проблема пробелов и островков:

WITH VTE AS (
    SELECT *    
    FROM (VALUES(1,47676,CONVERT(date,NULL),CONVERT(date,'20150112'),CONVERT(date,'20151231')),
                (1,47676,CONVERT(date,'20151231'),CONVERT(date,'20150209'),CONVERT(date,NULL)),
                (1,47676,CONVERT(date,NULL),CONVERT(date,'20150224'),CONVERT(date,NULL)),
                (1,47676,CONVERT(date,NULL),CONVERT(date,'20151005'),CONVERT(date,NULL)),
                (1,47676,CONVERT(date,NULL),CONVERT(date,'20151021'),CONVERT(date,NULL)),
                (1,47676,CONVERT(date,NULL),CONVERT(date,'20151026'),CONVERT(date,NULL)),
                (1,47676,CONVERT(date,NULL),CONVERT(date,'20151120'),CONVERT(date,NULL))) V(tipoProtocolo,numeroProtocolo,dataReferencia,dataAssinatura,dataVencimento)),
Grps AS(
    SELECT V.tipoProtocolo,
           V.numeroProtocolo,
           V.dataReferencia,
           V.dataAssinatura,
           V.dataVencimento,
           COUNT(dataVencimento)  OVER (PARTITION BY numeroProtocolo, tipoProtocolo ORDER BY dataAssinatura
                                        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Grp
    FROM VTE V)
SELECT G.tipoProtocolo,
       G.numeroProtocolo,
       G.dataReferencia,
       G.dataAssinatura,
       G.dataVencimento,
       MAX(dataVencimento) OVER (PARTITION BY G.Grp) AS dataReferencia,
       G.Grp
FROM Grps G
ORDER BY dataAssinatura;

Замечу, что странно, что вы называете столбец выражением LAG dataReferencia, несмотря на это. выражение находится на dataVencimento (и уже есть столбец с именем dataReferencia).

...