SQL Server如果没有可用的未来日期,请选择最近的过去日期

时间:2017-02-16 18:20:08

标签: sql sql-server

我有一个表结构如下,

CREATE TABLE #CustOrder ( CustId INT, OrderDate DATE )

INSERT #CustOrder ( CustId, OrderDate )
VALUES  ( 1, '2016-11-01' ),
        ( 1, '2019-09-01' ),
        ( 2, '2019-07-01' ),
        ( 2, '2019-11-01' ),
        ( 3, '2017-01-01' ),
        ( 4, '2016-12-01' ),
        ( 4, '2017-01-01' )

我想列出客户未来的订单日期,如果他们没有将来的订单,我想列出他们的最后或最近的订单。我有以下查询。

; WITH LastOrder AS
(
    SELECT 
        CO.CustId, 
        CO.OrderDate, 
        ROW_NUMBER() OVER(PARTITION BY CO.CustId ORDER BY ABS(DATEDIFF(DAY, CO.OrderDate, GETUTCDATE()))) AS RowNum 
    FROM #CustOrder AS CO

)
SELECT LO.CustId, LO.OrderDate
FROM LastOrder AS LO
WHERE LO.RowNum = 1

此查询将结果显示为

CustId  |   OrderDate
--------+-------------
1       |   2016-11-01
2       |   2019-07-01
3       |   2017-01-01
4       |   2017-01-01

但是,我需要结果为,

CustId  |   OrderDate
--------+-------------
1       |   2019-09-01
2       |   2019-07-01
3       |   2017-01-01
4       |   2017-01-01

作为

  1. 客户1的未来订单将于2019-09-01
  2. 客户2有两个未来订单,但第一个订单是2019-07-01
  3. 客户3订单不超过1个,应该返回2017-01-01
  4. 客户4有两个过去的订单,但最近的订单是2017-01-01

5 个答案:

答案 0 :(得分:2)

rextester:http://rextester.com/PBKNA95127

CREATE TABLE #CustOrder ( CustId INT, OrderDate DATE )

INSERT #CustOrder ( CustId, OrderDate )
VALUES  ( 1, '2016-11-01' ),
        ( 1, '2019-09-01' ),
        ( 2, '2019-07-01' ),
        ( 2, '2019-11-01' ),
        ( 3, '2017-01-01' ),
        ( 4, '2016-12-01' ),
        ( 4, '2017-01-01' )

; WITH LastOrder AS
(
    SELECT 
        CO.CustId, 
        CO.OrderDate, 
        ROW_NUMBER() OVER(PARTITION BY CO.CustId 
                          ORDER BY case when co.OrderDate > getdate() then 0 else 1 end
                          , abs(DATEDIFF(DAY, getdate(),CO.OrderDate)) asc
                         ) AS RowNum 
    FROM #CustOrder AS CO

)
SELECT LO.CustId, LO.OrderDate
FROM LastOrder AS LO
WHERE LO.RowNum = 1

结果:

+--------+------------+
| CustId | OrderDate  |
+--------+------------+
|      1 | 2019-09-01 |
|      2 | 2019-07-01 |
|      3 | 2017-01-01 |
|      4 | 2017-01-01 |
+--------+------------+

答案 1 :(得分:1)

您可以使用MAX功能检查最新日期是否在将来。如果是,请使用MIN在今天之后获取MIN日期。否则得到最新的日期。

SELECT CUSTID,OrderDate 
FROM (SELECT  CustId, 
              OrderDate, 
      CASE WHEN MAX(orderdate) OVER(PARTITION BY CustId) > GETUTCDATE() 
      THEN MIN(case when orderdate >getutcdate() then orderdate end) OVER(PARTITION BY CustId)
      ELSE MAX(orderdate) OVER(PARTITION BY CustId) end as latest_date
      FROM #CustOrder) T 
WHERE latest_date=orderDate

答案 2 :(得分:0)

使用CASE表达式开始你的ORDER BY,该表达式更喜欢将来的过去,然后使用ABS DATEDIFF(就像你现在一样)作为ORDER BY中的第二个条件。

答案 3 :(得分:0)

也许创建另一个列并使用LAG()窗口函数来获取最后一个日期函数,然后在select部分中放入一个条件/ case语句? https://msdn.microsoft.com/en-us/library/hh231256.aspx

答案 4 :(得分:0)

Min,Max,UNION方法

select custID, MIN(OrderDate)
  from #CustOrder 
  where OrderDate > '2017-02-17'
 group by custID 
union all 
select co1.custID, max(co1.OrderDate)
  from #CustOrder co1
 where not exists ( select 1 
                      from #CustOrder co2 
                     where co2.CustId = co1.CustId 
                       and co2.OrderDate > '2017-02-17' 
                  )
 group by co1.custID