您好,我是一名 SQL 初学者。我可以访问数据库进行研究,有一个感兴趣的表,结构如下:
|
|
|
|
---|---|---|---|
1 | 2023-02-01 | 90 | A |
1 | 2023-03-01 | 10 | B |
1 | 2023-03-15 | 15 | C |
2 | 2023-02-05 | 10 | B |
2 | 2023-02-13 | 30 | A |
这是由人员
item
完成的date
获取id
的表格。我想根据每个人员date
的重叠来转换此表id
,但不太确定如何实现这一点。
我想结果表如下:
|
|
|
|
---|---|---|---|
1 | 1 | 29 | A |
1 | 30 | 39 | A、B |
1 | 40 | 43 | A |
1 | 44 | 58 | A、C |
1 | 59 | 90 | A |
2 | 1 | 8 | B |
2 | 9 | 10 | A、B |
2 | 11 | 38 | A |
我的想法是:
我想使用
date
作为每个人员的起始索引来转换表格 id
这样,我们就可以将变换后的
date
转换为use
,从而获得相对的使用结束日期为start
+ use
- 1
|
|
|
|
|
---|---|---|---|---|
1 | 1 | 90 | 90 | A |
1 | 30 | 10 | 39 | B |
1 | 44 | 15 | 58 | C |
2 | 1 | 10 | 10 | B |
2 | 9 | 30 | 38 | A |
从视觉上看,每个人员的物品获取过程将是:
人员1:
+--------------C (15)
+---------B (10)
+------------------------------------------------------------------------------------------A (90)
+------------------------------+--------------+-------------------------------------------->
1 30 44 90
人员2:
+--------------------------------A (30)
+---------B (10)
+-------+-------------------------------->
1 9 40
最后,我可以评估并发项目获取如下:
|
|
|
|
---|---|---|---|
1 | 1 | 29 | A |
1 | 30 | 39 | A、B |
1 | 40 | 43 | A |
1 | 44 | 58 | A、C |
1 | 59 | 90 | A |
2 | 1 | 8 | B |
2 | 9 | 10 | A、B |
2 | 11 | 38 | A |
我找到了一些与这个问题相关的主题,包括:
-- Create a dummy table
CREATE TABLE tbl (
id int,
start_date date,
day_of_use int,
item varchar(8)
)
;
-- Populating table with sample data
INSERT INTO tbl VALUES (1, "2023-02-01", 90, "A");
INSERT INTO tbl VALUES (1, "2023-03-02", 10, "B");
INSERT INTO tbl VALUES (1, "2023-03-15", 15, "C");
INSERT INTO tbl VALUES (2, "2023-02-05", 10, "B");
INSERT INTO tbl VALUES (2, "2023-02-13", 30, "A");
-- Querying the overlap
SELECT
a.id,
DATEDIFF(a.start_date, b.init) + 1 AS start,
day_of_use,
DATEDIFF(a.start_date, b.init) + day_of_use AS end,
item
FROM
tbl AS a
LEFT JOIN
(
SELECT id, MIN(start_date) AS init
FROM tbl
GROUP BY id
ORDER BY id
) AS b ON a.id = b.id
;
不过,我不知道如何从这里开始。任何想法将不胜感激,提前致谢。 SQL小提琴:https://www.db-fiddle.com/f/eB1GnZTuuH5P71kr4pWqHu/2
如果您使用的是 MySQL 8.0,您可以尝试:
为了解决间隙和孤岛问题,您可能需要使用连续记录中项目更改量的运行总和来重新创建分区。
WITH RECURSIVE cte AS (
SELECT id, start_date AS date_, day_of_use, item
FROM tbl
UNION ALL
SELECT id, DATE_ADD(date_, INTERVAL 1 DAY), day_of_use-1, item
FROM cte
WHERE day_of_use > 0
), cte2 AS (
SELECT id,
DENSE_RANK() OVER(PARTITION BY id ORDER BY date_) AS rn,
item
FROM cte
), cte3 AS (
SELECT id,
rn,
GROUP_CONCAT(item ORDER BY item) AS items,
LAG(GROUP_CONCAT(item ORDER BY item)) OVER(PARTITION BY id) AS prev_items
FROM cte2
GROUP BY id, rn
), cte4 AS (
SELECT id, rn, items,
COUNT(CASE WHEN prev_items != items THEN 1 END) OVER(PARTITION BY id ORDER BY rn) AS parts
FROM cte3
)
SELECT id, MIN(rn) AS start_, MAX(rn) AS end_, items
FROM cte4
GROUP BY id, items, parts
“输出”:
id | 项目 | 开始_ | 完_ |
---|---|---|---|
1 | A | 1 | 29 |
1 | A、B | 30 | 40 |
1 | A | 41 | 42 |
1 | A、C | 43 | 58 |
1 | A | 59 | 91 |
2 | B | 1 | 8 |
2 | A、B | 9 | 11 |
2 | A | 12 | 39 |
查看演示这里。
请注意,2023 年 2 月没有 29 天。