所以我有一个这样的数据库
ITEM STOCK DAY
A 5 2024-08-12
B 2 2024-08-12
C 7 2024-08-12
A 3 2024-08-13
B 2 2024-08-13
C 7 2024-08-13
D 1 2024-08-13
A 3 2024-08-14
B 3 2024-08-15
C 7 2024-08-14
A 3 2024-08-15
B 3 2024-08-15
C 9 2024-08-15
A 2 2024-08-16
B 3 2024-08-16
C 7 2024-08-16
A 5 2024-08-17
B 2 2024-08-17
C 7 2024-08-17
D 3 2024-08-17
我想做的是使用窗口函数检查具有相同库存的商品的连续天数。
预期的结果会是这样的。 (连续的天数将写为CDAYS)
ITEM CDAYS DAY_START DAY_END
A 0 2024-08-12 2024-08-12
B 1 2024-08-12 2024-08-13
C 5 2024-08-12 2024-08-17
A 2 2024-08-13 2024-08-15
D 0 2024-08-13 2024-08-13
B 2 2024-08-14 2024-08-16
A 0 2024-08-16 2024-08-16
A 0 2024-08-17 2024-08-17
B 0 2024-08-17 2024-08-17
D 0 2024-08-17 2024-08-17
我尝试制作自己的窗口函数来解决这个问题,但失败了。
然而,我确实发现了问题所在。
像这样使用SQL
create table mytable (ITEM char, STOCK int, DATE date);
insert into mytable values
('A', 5, '2024-08-12'),
('B', 2, '2024-08-12'),
('C', 7, '2024-08-12'),
('A', 3, '2024-08-13'),
('B', 2, '2024-08-13'),
('C', 7, '2024-08-13'),
('D', 1, '2024-08-13'),
('A', 3, '2024-08-14'),
('B', 3, '2024-08-14'),
('C', 7, '2024-08-14'),
('A', 3, '2024-08-15'),
('B', 3, '2024-08-15'),
('C', 7, '2024-08-15'),
('A', 2, '2024-08-16'),
('B', 3, '2024-08-16'),
('C', 7, '2024-08-16'),
('A', 5, '2024-08-17'),
('B', 2, '2024-08-17'),
('C', 7, '2024-08-17'),
('D', 3, '2024-08-17');
SELECT ITEM, STOCK,
ROW_NUMBER() OVER (PARTITION BY ITEM, STOCK ORDER BY DATE) AS Cdays, DATE
FROM mytable
ORDER BY ITEM, DATE
我得到如下结果
item stock cdays date
A 5 1 2024-08-12
A 3 1 2024-08-13
A 3 2 2024-08-14
A 3 3 2024-08-15
A 2 1 2024-08-16
A 5 2 2024-08-17
B 2 1 2024-08-12
B 2 2 2024-08-13
B 3 1 2024-08-14
B 3 2 2024-08-15
B 3 3 2024-08-16
B 2 3 2024-08-17
C 7 1 2024-08-12
C 7 2 2024-08-13
C 7 3 2024-08-14
C 7 4 2024-08-15
C 7 5 2024-08-16
C 7 6 2024-08-17
D 1 1 2024-08-13
D 3 1 2024-08-17
查看项目 A,cdays 应该是 1 1 2 3 1 1,而不是 1 1 2 3 1 2。
如何修改我的 SQL,以便 2014 年 8 月 12 日和 2014 年 8 月 17 日的商品 A 库存不被视为连续数据?
这是源自 Itzik Ben-Gan 的技术 1 的一种方法(我关于间隙和岛屿问题的首选文章):
WITH grps AS
(
SELECT ITEM,
STOCK,
ROW_NUMBER() OVER (PARTITION BY ITEM ORDER BY DATE) -
ROW_NUMBER() OVER (PARTITION BY ITEM, STOCK ORDER BY DATE) AS grp,
DATE
FROM mytable
)
SELECT ITEM, STOCK, cdays = ROW_NUMBER() OVER
(PARTITION BY ITEM, grp, STOCK ORDER BY DATE), DATE
FROM grps
ORDER BY ITEM, DATE;