【问题标题】:Running total with respect to another column in SQL Server相对于 SQL Server 中的另一列运行总计
【发布时间】:2018-11-04 17:26:19
【问题描述】:

我有一张表格,上面有代表员工的姓名和日期以及他们工作的日期。我想创建他们工作的总天数,如果连续性中断,那么我想注意他们恢复工作之前的休息时间。

这是实际数据:

+------+---------------------+
| Name |        Date         |
+------+---------------------+
| Adam | 01/01/2018 00:00:00 |
| Adam | 02/01/2018 00:00:00 |
| Adam | 03/01/2018 00:00:00 |
| Adam | 15/01/2018 00:00:00 |
| Ben  | 02/01/2018 00:00:00 |
| Ben  | 03/01/2018 00:00:00 |
+------+---------------------+

这是预期的结果:

+------+---------------------+------------------+---------+
| Name |        Date         | Consecutive_days | Holiday |
+------+---------------------+------------------+---------+
| Adam | 01/01/2018 00:00:00 |                1 |       0 |
| Adam | 02/01/2018 00:00:00 |                2 |       0 |
| Adam | 03/01/2018 00:00:00 |                3 |       0 |
| Adam | 15/01/2018 00:00:00 |                1 |      12 |
| Ben  | 02/01/2018 00:00:00 |                1 |       0 |
| Ben  | 03/01/2018 00:00:00 |                2 |       0 |
+------+---------------------+------------------+---------+

我知道我应该使用 SUM() OVER(ORDER BY Date) 子句,一旦我发现连续天之间的差异,但我无法弄清楚如何获得这些差异。

【问题讨论】:

  • 您的预期结果是什么?
  • @D-Shih 预期的结果已经发布(如果我理解正确的话)。
  • 名称和日期列已给出。其他两个应该确定
  • @BlazejKowalski 更新问题,以便读者清楚。

标签: sql-server cumulative-sum


【解决方案1】:

我想你想要类似的东西

CREATE TABLE T
    ([Name] varchar(4), [Date] datetime, [Consecutive_days] int);

INSERT INTO T
    ([Name], [Date], [Consecutive_days])
VALUES
    ('Adam', '2018-01-01 00:00:00', 1),
    ('Adam', '2018-01-02 00:00:00', 2),
    ('Adam', '2018-01-03 00:00:00', 3),
    ('Adam', '2018-01-15 00:00:00', 1),
    ('Ben', '2018-01-02 00:00:00', 1),
    ('Ben', '2018-01-03 00:00:00', 2);

WITH C AS
(
SELECT *,
       LAG([Date], 1, 0) OVER(ORDER BY [Date]) L
FROM T
)
SELECT Name,
       [Date],
       Consecutive_days,
       CASE WHEN DATEDIFF(Day, L, [Date]) > 1
                 AND
                 DATEDIFF(Day, L, [Date]) < 360
                 THEN
            DATEDIFF(Day, L, [Date])
            ELSE
            0 END Holiday

FROM C
ORDER BY Name;

返回:

+------+---------------------+------------------+---------+
| Name |        Date         | Consecutive_days | Holiday |
+------+---------------------+------------------+---------+
| Adam | 01/01/2018 00:00:00 |                1 |       0 |
| Adam | 02/01/2018 00:00:00 |                2 |       0 |
| Adam | 03/01/2018 00:00:00 |                3 |       0 |
| Adam | 15/01/2018 00:00:00 |                1 |      12 |
| Ben  | 02/01/2018 00:00:00 |                1 |       0 |
| Ben  | 03/01/2018 00:00:00 |                2 |       0 |
+------+---------------------+------------------+---------+

创建他们工作的总天数,如果连续性中断,那么我想注意在他们恢复工作之前中断了多长时间

你可以这样做

SELECT Name + ' has works ' + CAST(SUM(Consecutive_days) AS VARCHAR(10))+
                ' days, and '+
                CAST(SUM(Holiday) AS VARCHAR(10))+
                ' holidays' Result
FROM T
GROUP BY Name;

返回:

+----------------------------------------+
|                 Result                 |
+----------------------------------------+
| Adam has works 7 days, and 12 holidays |
| Ben has works 3 days, and 0 holidays   |
+----------------------------------------+

根据您的comment更新

CREATE TABLE T
    ([Name] varchar(4), [Date] datetime);

INSERT INTO T
    ([Name], [Date])
VALUES
    ('Adam', '2018-01-01 00:00:00'),
    ('Adam', '2018-01-02 00:00:00'),
    ('Adam', '2018-01-03 00:00:00'),
    ('Adam', '2018-01-15 00:00:00'),
    ('Ben', '2018-01-02 00:00:00'),
    ('Ben', '2018-01-03 00:00:00');

SELECT T1.*,
       CASE WHEN
                 DATEDIFF(Day, X.[Date], T1.[Date]) > 1 THEN 1 
            ELSE
                 ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Name)
            END Consecutive_days,
       CASE WHEN DATEDIFF(Day, X.[Date], T1.[Date]) IS NULL
                 OR
                 DATEDIFF(Day, X.[Date], T1.[Date]) = 1
                 THEN 0
                 ELSE
                 DATEDIFF(Day, X.[Date], T1.[Date])
                 END

FROM T T1 OUTER APPLY
(
SELECT TOP 1 [Date] 
FROM T T2 
WHERE T2.[Date] < T1.[Date] 
ORDER BY T2.[Date] DESC
) X;

返回:

+------+---------------------+------------------+---------+
| Name |        Date         | Consecutive_days | Holiday |
+------+---------------------+------------------+---------+
| Adam | 01/01/2018 00:00:00 |                1 |       0 |
| Adam | 02/01/2018 00:00:00 |                2 |       0 |
| Adam | 03/01/2018 00:00:00 |                3 |       0 |
| Adam | 15/01/2018 00:00:00 |                1 |      12 |
| Ben  | 02/01/2018 00:00:00 |                1 |       0 |
| Ben  | 03/01/2018 00:00:00 |                2 |       0 |
+------+---------------------+------------------+---------+

【讨论】:

  • 未给出“Consecutive_days”列。应根据日期列确定
  • @BlazejKowalski 你的问题不够清楚,我会更新我的答案
猜你喜欢
  • 2021-03-27
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 2010-10-26
  • 2018-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多