【问题标题】:DATEDIFF with variable seed带有可变种子的 DATEDIFF
【发布时间】:2020-02-14 02:08:52
【问题描述】:

我有下表

第一列是按日期 DESC 排序的交易日期。 第二列是每个事务的二进制状态,可以是 0 或 1。 第三列是与每个日期相比的最小日期的日期差异。 生成这个表的代码是这样的

DECLARE @date DATE 
SELECT @Date = MIN(CONVERT(DATE,Transaction_Created)) FROM #dates
SELECT      CONVERT(DATE,Transaction_Created)                       AS Date
    ,       MAX(Is_Deposit)                                         AS Is_Deposit
    ,       DATEDIFF(dd,@Date,CONVERT(DATE,Transaction_Created))    AS Datedif  

FROM        #DATES
GROUP BY    CONVERT(DATE,Transaction_Created)
order by 1 desc

我的问题是,当 is_Deposit=1 时,我需要为 DATEDIFF 重置我的种子,并且 IS_Deposit =1 的日期成为我在表中找到的每个 IS_Deposit=1 的新最小日期等等。 例如,从 2015 年 12 月 4 日到 2015 年 12 月 16 日,一切正常。但是在第 746 行 2015-12-17 我希望它再次成为 1 而不是 13,因为我们已经达到了下一个 IS_Deposit=1 并且我们必须重置。

现在的结果集:

Date    Is_Deposit  Datedif

2016-02-12  0   70
2016-02-11  0   69
2016-02-10  0   68
2016-02-09  0   67
2016-02-08  0   66
2016-02-07  0   65
2016-02-06  0   64
2016-02-05  0   63
2016-02-04  0   62
2016-02-03  0   61
2016-02-02  0   60
2016-02-01  0   59
2016-01-31  0   58
2016-01-30  0   57
2016-01-29  0   56
2016-01-28  0   55
2016-01-27  0   54
2016-01-26  0   53
2016-01-25  0   52
2016-01-24  0   51
2016-01-23  0   50
2016-01-22  0   49
2016-01-21  0   48
2016-01-20  1   47
2016-01-17  0   44
2016-01-16  0   43
2016-01-15  0   42
2016-01-14  0   41
2016-01-13  0   40
2016-01-12  0   39
2016-01-11  0   38
2016-01-10  0   37
2016-01-09  0   36
2016-01-08  0   35
2016-01-07  0   34
2016-01-06  0   33
2016-01-05  0   32
2016-01-04  0   31
2016-01-03  0   30
2016-01-02  0   29
2016-01-01  0   28
2015-12-31  0   27
2015-12-30  0   26
2015-12-29  0   25
2015-12-28  0   24
2015-12-27  0   23
2015-12-26  0   22
2015-12-25  1   21
2015-12-20  0   16
2015-12-19  0   15
2015-12-18  0   14
2015-12-17  0   13
2015-12-16  1   12
2015-12-14  0   10
2015-12-13  0   9
2015-12-12  0   8
2015-12-11  0   7
2015-12-10  0   6
2015-12-09  0   5
2015-12-08  0   4
2015-12-07  0   3
2015-12-05  0   1
2015-12-04  1   0

需要结果集:

2016-02-12  0   23

2016-02-11  0   22
2016-02-10  0   21
2016-02-09  0   20
2016-02-08  0   19
2016-02-07  0   18
2016-02-06  0   17
2016-02-05  0   16
2016-02-04  0   15
2016-02-03  0   14
2016-02-02  0   13
2016-02-01  0   12
2016-01-31  0   11
2016-01-30  0   10
2016-01-29  0   9
2016-01-28  0   8
2016-01-27  0   7
2016-01-26  0   6
2016-01-25  0   5
2016-01-24  0   4
2016-01-23  0   3
2016-01-22  0   2
2016-01-21  0   1
2016-01-20  1   26
2016-01-17  0   23
2016-01-16  0   22
2016-01-15  0   21
2016-01-14  0   20
2016-01-13  0   19
2016-01-12  0   18
2016-01-11  0   17
2016-01-10  0   16
2016-01-09  0   15
2016-01-08  0   14
2016-01-07  0   13
2016-01-06  0   12
2016-01-05  0   11
2016-01-04  0   10
2016-01-03  0   9
2016-01-02  0   8
2016-01-01  0   7
2015-12-31  0   6
2015-12-30  0   5
2015-12-29  0   4
2015-12-28  0   3
2015-12-27  0   2
2015-12-26  0   1
2015-12-25  1   9
2015-12-20  0   4
2015-12-19  0   3
2015-12-18  0   2
2015-12-17  0   1
2015-12-16  1   12
2015-12-14  0   10
2015-12-13  0   9
2015-12-12  0   8
2015-12-11  0   7
2015-12-10  0   6
2015-12-09  0   5
2015-12-08  0   4
2015-12-07  0   3
2015-12-05  0   1
2015-12-04  1   0

【问题讨论】:

  • 请不要提供表格的图片。如果您要提供数据,请使用表格格式的text,或者(甚至更好)以及 DDL 和 DML 语句。然后我们可以使用您的数据并对其进行测试。您对这里的数据集的预期结果是什么?另外,你真的应该避免按序号位置排序:Bad habits to kick : ORDER BY ordinal
  • 不客气。请务必用一些要点更新您的问题(消耗性样本数据和预期结果对于我们能够轻松为您提供帮助非常重要)。许多用户会忽略带有数据图像的帖子,因为图像对他们没有用处,无法帮助您。

标签: sql sql-server database tsql datediff


【解决方案1】:

您可以使用几个窗口函数来做到这一点。首先是运行总计来构建一个累积序列 ID,然后在每个序列中挑选出最小值:

With 
DatesSequence AS
(
SELECT Date,Is_Deposit
, SUM(Is_Deposit) OVER(ORDER BY Date DESC) AS Sequence
FROM #Dates
)
SELECT 
Date
,Is_Deposit
, DATEDIFF(day,
            MIN(Date) OVER (PARTITION BY Sequence),
            Date) + 1 AS DateDif
FROM DatesSequence

【讨论】:

    【解决方案2】:

    一个简单的子查询就可以解决这个问题。
    首先,创建并填充示例表(在您以后的问题中保存我们这一步):

    DECLARE @T AS TABLE
    (
        Date date,
        Is_Deposit bit,
        Datedif int
    );
    
    INSERT INTO @T (Date, Is_Deposit, Datedif) VALUES
    ('2016-02-12', 0, 70),
    ('2016-02-11', 0, 69),
    ('2016-02-10', 0, 68),
    ('2016-02-09', 0, 67),
    ('2016-02-08', 0, 66),
    ('2016-02-07', 0, 65),
    ('2016-02-06', 0, 64),
    ('2016-02-05', 0, 63),
    ('2016-02-04', 0, 62),
    ('2016-02-03', 0, 61),
    ('2016-02-02', 0, 60),
    ('2016-02-01', 0, 59),
    ('2016-01-31', 0, 58),
    ('2016-01-30', 0, 57),
    ('2016-01-29', 0, 56),
    ('2016-01-28', 0, 55),
    ('2016-01-27', 0, 54),
    ('2016-01-26', 0, 53),
    ('2016-01-25', 0, 52),
    ('2016-01-24', 0, 51),
    ('2016-01-23', 0, 50),
    ('2016-01-22', 0, 49),
    ('2016-01-21', 0, 48),
    ('2016-01-20', 1, 47),
    ('2016-01-17', 0, 44),
    ('2016-01-16', 0, 43),
    ('2016-01-15', 0, 42),
    ('2016-01-14', 0, 41),
    ('2016-01-13', 0, 40),
    ('2016-01-12', 0, 39),
    ('2016-01-11', 0, 38),
    ('2016-01-10', 0, 37),
    ('2016-01-09', 0, 36),
    ('2016-01-08', 0, 35),
    ('2016-01-07', 0, 34),
    ('2016-01-06', 0, 33),
    ('2016-01-05', 0, 32),
    ('2016-01-04', 0, 31),
    ('2016-01-03', 0, 30),
    ('2016-01-02', 0, 29),
    ('2016-01-01', 0, 28),
    ('2015-12-31', 0, 27),
    ('2015-12-30', 0, 26),
    ('2015-12-29', 0, 25),
    ('2015-12-28', 0, 24),
    ('2015-12-27', 0, 23),
    ('2015-12-26', 0, 22),
    ('2015-12-25', 1, 21),
    ('2015-12-20', 0, 16),
    ('2015-12-19', 0, 15),
    ('2015-12-18', 0, 14),
    ('2015-12-17', 0, 13),
    ('2015-12-16', 1, 12),
    ('2015-12-14', 0, 10),
    ('2015-12-13', 0, 9 ),
    ('2015-12-12', 0, 8 ),
    ('2015-12-11', 0, 7 ),
    ('2015-12-10', 0, 6 ),
    ('2015-12-09', 0, 5 ),
    ('2015-12-08', 0, 4 ),
    ('2015-12-07', 0, 3 ),
    ('2015-12-05', 0, 1 ),
    ('2015-12-04', 1, 0 );
    

    查询:

    SELECT    Date
            , Is_Deposit
            , DATEDIFF(
                DAY, 
                (
                    SELECT TOP 1 Date 
                    FROM @T AS t1 
                    WHERE t1.Date <= t0.Date 
                    AND Is_Deposit = 1
                ), 
                Date
            ) As Datedif
    FROM @T As t0
    

    结果:

    Date        Is_Deposit  Datedif
    2016-02-12  0           23
    2016-02-11  0           22
    2016-02-10  0           21
    2016-02-09  0           20
    2016-02-08  0           19
    2016-02-07  0           18
    2016-02-06  0           17
    2016-02-05  0           16
    2016-02-04  0           15
    2016-02-03  0           14
    2016-02-02  0           13
    2016-02-01  0           12
    2016-01-31  0           11
    2016-01-30  0           10
    2016-01-29  0           9
    2016-01-28  0           8
    2016-01-27  0           7
    2016-01-26  0           6
    2016-01-25  0           5
    2016-01-24  0           4
    2016-01-23  0           3
    2016-01-22  0           2
    2016-01-21  0           1
    2016-01-20  1           0
    2016-01-17  0           23
    2016-01-16  0           22
    2016-01-15  0           21
    2016-01-14  0           20
    2016-01-13  0           19
    2016-01-12  0           18
    2016-01-11  0           17
    2016-01-10  0           16
    2016-01-09  0           15
    2016-01-08  0           14
    2016-01-07  0           13
    2016-01-06  0           12
    2016-01-05  0           11
    2016-01-04  0           10
    2016-01-03  0           9
    2016-01-02  0           8
    2016-01-01  0           7
    2015-12-31  0           6
    2015-12-30  0           5
    2015-12-29  0           4
    2015-12-28  0           3
    2015-12-27  0           2
    2015-12-26  0           1
    2015-12-25  1           0
    2015-12-20  0           4
    2015-12-19  0           3
    2015-12-18  0           2
    2015-12-17  0           1
    2015-12-16  1           0
    2015-12-14  0           10
    2015-12-13  0           9
    2015-12-12  0           8
    2015-12-11  0           7
    2015-12-10  0           6
    2015-12-09  0           5
    2015-12-08  0           4
    2015-12-07  0           3
    2015-12-05  0           1
    2015-12-04  1           0
    

    如果要更新表,可以将查询改为 cte 并像这样更新:

    WITH CTE AS
    (
        SELECT    Date
                , Is_Deposit
                , Datedif
                , DATEDIFF(
                    DAY, 
                    (
                        SELECT TOP 1 Date 
                        FROM @T AS t1 
                        WHERE t1.Date <= t0.Date 
                        AND Is_Deposit = 1
                    ), 
                    Date
                ) As NewDatedif
        FROM @T As t0
    )
    
    UPDATE CTE 
    SET dateDif = NewDateDif;
    

    【讨论】:

      【解决方案3】:

      我认为您可以只使用累积条件max()。我不知道是否真的需要聚合,所以这可能会满足你的需求:

      SELECT Date, Is_Deposit,
             COALESCE(DATEDIFF(day,
                               date,
                               MAX(CASE WHEN Is_Deposit = 1 THEN DATE END) OVER
                                   (ORDER BY Date
                                    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
                                   )
                              ), 0
                     )
      FROM #Dates
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-30
        • 2020-08-16
        • 1970-01-01
        • 2018-04-15
        • 1970-01-01
        • 1970-01-01
        • 2021-09-05
        相关资源
        最近更新 更多