1

我有一个如下行的表:

在这里你有一个问题插画

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 列(图像中的红色箭头)。但是,我想检查 dataVencimento 列(来自上一行)是否为 NULL。如果此条件为真,我需要从前一行的 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
4

2 回答 2

2

你想要的是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;

子查询计算有效值的数量。这实际上是为行分配组号。然后,外部查询将值传播到整个组。

于 2019-10-01T13:59:57.110 回答
0

由于 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)),
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表达式调用列似乎很奇怪。dataReferenciadataVencimentodataReferencia

于 2019-10-01T14:46:19.567 回答