SQL查找记录的null和prev记录不为null

时间:2017-10-26 06:28:25

标签: sql sql-server tsql ssms

这里我想要customerID的结果,对于相同的CID,offerd具有null和prevoius提供日期不为null。

CURRENT结果:

            CID             orderDate           offerdate1   
            1               2015-08-11          2014-08-10
            1               2015-08-12          2014-08-11
            1               2015-08-12          NULL                
            2               2016-08-13          2015-08-11
            2               2016-08-13          2015-08-12
            3               2016-08-13          NULL
            4               2016-01-12          2016-01-12
            4               2016-02-12          Null

预期结果:

            CID             orderDate           offerdate1   
            1               2015-08-12          2014-08-11
            1               2015-08-12          NULL
            4               2016-01-12          2016-01-12
            4               2016-02-12          Null

例如。对于CID ='1' 最近的订单日期是2015-08-12,报价日期为NULL。 但同样的CID在prevoius orderdate.i.e.'2014-08-11上提供了日期 所以我只想要记录,其中offerdate为null,但在之前的orderdate上提供了剃须报价。

4 个答案:

答案 0 :(得分:2)

尝试窗口功能。 LAG(offerdate)允许您检测前一个为NULL的{​​{1}}行,NOT NULL允许您检测NULL行前面的行。

LEAD(offerdate), LEAD(orderdate)

demo

我的解决方案假设今天的日期之后没有日期。如果不是这样,那么将我的解决方案中的select t.cid, t.orderdate, t.offerdate from ( select *, lag(offerdate) over (partition by cid order by orderdate, coalesce(offerdate,getdate())) offerlag, lead(offerdate) over (partition by cid order by orderdate, coalesce(offerdate,getdate())) offerlead, lead(orderdate) over (partition by cid order by orderdate, coalesce(offerdate,getdate())) orderlead from your_table ) t where t.offerdate is null and t.offerlag is not null or -- NULL row detection t.offerdate is not null and t.offerlead is null and t.orderlead is not null -- row preceding the NULL row detection order by cid, orderdate, coalesce(offerdate,getdate()) 替换为大于数据库中任何日期的某个日期。例如,如果您在数据库中也有今天的日期(并且没有将来的日期),那么您可以getdate()替换getDate()

答案 1 :(得分:1)

对于SQL Server 2008以及稍后您可以使用:

DECLARE @DataSource TABLE
(
    [CID] INT
   ,[orderDate] DATE
   ,[offerdate1] DATE
);

INSERT INTO @DataSource ([CID], [orderDate], [offerdate1])
VALUES (1, '2015-08-11', '2014-08-10')
      ,(1, '2015-08-12', '2014-08-11')
      ,(1, '2015-08-12', NULL)
      ,(2, '2016-08-13', '2015-08-11')
      ,(2, '2016-08-13', '2015-08-12')
      ,(3, '2016-08-13', NULL)
      ,(4, '2016-01-12', '2016-01-12')
      ,(4, '2016-02-12', NULL);

WITH DataSource AS
(
    SELECT *
          ,ROW_NUMBER() OVER(PARTITION BY [CID] ORDER BY [orderDate], [offerdate1] DESC) AS [RowID]
    FROM @DataSource
),
FinalDataSource AS
(
    SELECT DS1.[CID]
          ,DS1.[orderDate]
          ,DS1.[offerdate1]
          ,DS2.[CID] AS DS2_CID
          ,DS2.[orderDate] AS DS2_orderDate
          ,DS2.[offerdate1] AS DS2_offerdate1
    FROM DataSource DS1
    INNER JOIN DataSource DS2
        ON DS1.[CID] = DS2.[CID]
        AND DS1.[RowID] = DS2.[RowID] + 1
    WHERE DS1.[offerdate1] IS NULL
)
SELECT [CID]
      ,[orderDate]
      ,[offerdate1]
FROM FinalDataSource
UNION ALL
SELECT [DS2_CID]
      ,[DS2_orderDate]
      ,[DS2_offerdate1]
FROM FinalDataSource;

enter image description here

答案 2 :(得分:0)

我已插入来自" CURRENT结果的数据:"进入新表t1及以下表格,你有预期的结果:

select * from (
    select * from t1 where cid in
        (select cid from t1 where offerdate1 is null group by cid) and cid  not in
        (select cid from (  
        (select cid, min(offerdate1), max(offerdate1) from t1 having min(offerdate1) is null group by cid))) and offerdate1 is null
    union all
    select cid, min(orderdate), max(offerdate1) from (
        select * from t1 where cid in
        (select cid from t1 where offerdate1 is null group by cid) and cid  not in
        (select cid from (  
        (select cid, min(offerdate1), max(offerdate1) from t1 having min(offerdate1) is null group by cid)))) group by cid
) order by cid, orderdate;

答案 3 :(得分:0)

        select  b.cid,
                b.orderDate,
                b.offerdate1  
        from 
        (
        select  cid,
                orderDate,
                offerdate1  
        From #temp  A
        where A.offerdate1 is null 
        and exists ( 
        select 1 from #temp B 
        where   a.cid = b.cid 
        and     B.offerdate1 is not  null  )

        ) a 
        inner join #temp b
        on a.cid = b.cid
        where b.offerdate1 = (select max(offerdate1) from  #temp C where c.cid = a.cid )

        union all

        select  cid,
                orderDate,
                offerdate1  
        From #temp  A
        where A.offerdate1 is null 
        and exists ( 
        select 1 from #temp B 
        where   a.cid = b.cid 
        and     B.offerdate1 is not  null  )
        order by cid,offerdate1 desc