如何为 SQL 中的每个帐户 ID 从第一行中减去下一行?
How to subtract next row from first one for each account id in SQL?
我要回答的问题是如何 return 每个 ID 的正确顺序和星期顺序?例如,虽然每个 ID 的第一周确实总是从 1 开始(它是系列中的第一周),但系列中的下一个日期也可能在第一周内(例如,return 1)或者可能是第 3 周的日期(例如,return 3 也应该如此)。
到目前为止我写的代码是:
select distinct
row_number() over (partition by ID group by date) row_nums
,ID
,date
from table_a
这只是 return运行 按 ID 计算的日期总数,并没有考虑该日期所在的周数。
但我要找的是这个:
这里有一些设置代码可以提供帮助:
CREATE TABLE random_table
(
ID VarChar(50),
date DATETIME
);
INSERT INTO random_table
VALUES
('AAA',5/14/2021),
('AAA',6/2/2021),
('AAA',7/9/2021),
('BBB', 5/25/2021),
('CCC', 12/2/2020),
('CCC',12/6/2020),
('CCC',12/10/2020),
('CCC',12/14/2020),
('CCC',12/18/2020),
('CCC',12/22/2020),
('CCC',12/26/2020),
('CCC',12/30/2020),
('CCC',1/3/2021),
('DDD',1/7/2021),
('DDD',1/11/2021)
您的 objective 不清楚,但我认为您会受益于 Tally-Table 周然后 LEFT JOIN 到您的源数据。
这将为您提供每周一行和源数据(如果存在)
with adj as (
select *, dateadd(day, -1, "date") as adj_dt
from table_a
)
select
datediff(week,
min(adj_dt) over (partition by id),
adj_dt) + 1 as week_logic,
id, "date"
from adj
这假设您对周的想法与 @@datefirst
设置为星期日相对应。对于星期日到星期六的定义,您会在同一周内找到 12/06/2020 和 12/10/2020,因此大概您想要类似星期一的开始(这似乎也与 12/02/ 的编号一致) 2020、12/14/2020 和 12/18/2020。)我通过在周计算中向后滑动一天来进行补偿。该步骤可以在没有 CTE 的情况下在线处理,但也许它更清楚地说明了该方法。
SELECT
CASE WHEN ROW_NUMBER() OVER (PARTITION BY ID ORDER BY [date])=1 THEN 1
ELSE DATEPART(WK, (DATE) ) - DATEPART(WK, FIRST_VALUE([DATE]) OVER (PARTITION BY ID ORDER BY [date])) END PD,
ID,
CONVERT(VARCHAR(10), [date],120)
FROM random_table rt
ORDER BY ID,[date]
输出:
PD
ID
(No column name)
1
AAA
2021-05-14
3
AAA
2021-06-02
8
AAA
2021-07-09
1
BBB
2021-05-25
1
CCC
2020-12-02
1
CCC
2020-12-06
1
CCC
2020-12-10
2
CCC
2020-12-14
2
CCC
2020-12-18
3
CCC
2020-12-22
3
CCC
2020-12-26
4
CCC
2020-12-30
-47
CCC
2021-01-03
1
DDD
2021-01-07
1
DDD
2021-01-11
- 日期格式为
YYYY-MM-DD
。
- 我会把
-47
留在这里,所以你可以自己修复它(作为练习)
我要回答的问题是如何 return 每个 ID 的正确顺序和星期顺序?例如,虽然每个 ID 的第一周确实总是从 1 开始(它是系列中的第一周),但系列中的下一个日期也可能在第一周内(例如,return 1)或者可能是第 3 周的日期(例如,return 3 也应该如此)。
到目前为止我写的代码是:
select distinct
row_number() over (partition by ID group by date) row_nums
,ID
,date
from table_a
这只是 return运行 按 ID 计算的日期总数,并没有考虑该日期所在的周数。
但我要找的是这个:
这里有一些设置代码可以提供帮助:
CREATE TABLE random_table
(
ID VarChar(50),
date DATETIME
);
INSERT INTO random_table
VALUES
('AAA',5/14/2021),
('AAA',6/2/2021),
('AAA',7/9/2021),
('BBB', 5/25/2021),
('CCC', 12/2/2020),
('CCC',12/6/2020),
('CCC',12/10/2020),
('CCC',12/14/2020),
('CCC',12/18/2020),
('CCC',12/22/2020),
('CCC',12/26/2020),
('CCC',12/30/2020),
('CCC',1/3/2021),
('DDD',1/7/2021),
('DDD',1/11/2021)
您的 objective 不清楚,但我认为您会受益于 Tally-Table 周然后 LEFT JOIN 到您的源数据。 这将为您提供每周一行和源数据(如果存在)
with adj as (
select *, dateadd(day, -1, "date") as adj_dt
from table_a
)
select
datediff(week,
min(adj_dt) over (partition by id),
adj_dt) + 1 as week_logic,
id, "date"
from adj
这假设您对周的想法与 @@datefirst
设置为星期日相对应。对于星期日到星期六的定义,您会在同一周内找到 12/06/2020 和 12/10/2020,因此大概您想要类似星期一的开始(这似乎也与 12/02/ 的编号一致) 2020、12/14/2020 和 12/18/2020。)我通过在周计算中向后滑动一天来进行补偿。该步骤可以在没有 CTE 的情况下在线处理,但也许它更清楚地说明了该方法。
SELECT
CASE WHEN ROW_NUMBER() OVER (PARTITION BY ID ORDER BY [date])=1 THEN 1
ELSE DATEPART(WK, (DATE) ) - DATEPART(WK, FIRST_VALUE([DATE]) OVER (PARTITION BY ID ORDER BY [date])) END PD,
ID,
CONVERT(VARCHAR(10), [date],120)
FROM random_table rt
ORDER BY ID,[date]
输出:
PD | ID | (No column name) |
---|---|---|
1 | AAA | 2021-05-14 |
3 | AAA | 2021-06-02 |
8 | AAA | 2021-07-09 |
1 | BBB | 2021-05-25 |
1 | CCC | 2020-12-02 |
1 | CCC | 2020-12-06 |
1 | CCC | 2020-12-10 |
2 | CCC | 2020-12-14 |
2 | CCC | 2020-12-18 |
3 | CCC | 2020-12-22 |
3 | CCC | 2020-12-26 |
4 | CCC | 2020-12-30 |
-47 | CCC | 2021-01-03 |
1 | DDD | 2021-01-07 |
1 | DDD | 2021-01-11 |
- 日期格式为
YYYY-MM-DD
。 - 我会把
-47
留在这里,所以你可以自己修复它(作为练习)