我很难找到 MySQL 工作区,所以最初我提出了一个 T-SQL 解决方案,但后来在 rextester 学习了如何使用 MySQL,这对我有很大帮助。 MySQL 中 DATEDIFF() 函数的语法与 T-SQL 的逻辑相反,后者变得复杂而无法对其进行测试。希望现在解决了。
这种方法的基本逻辑是计算父母的总时长。然后计算所有孩子的持续时间的总和。然后比较这些持续时间(在连接中),如果它们相同,则没有间隙。
请注意,此逻辑未针对子项中的重叠进行测试,但我希望这些逻辑在比较持续时间的连接处也会失败。
数据:
#drop table if exists `PRICELIST`;
create table `PRICELIST`
(`id` int, `parent_id` int, `date_start` datetime, `date_end` datetime)
;
INSERT INTO PRICELIST
(`id`, `parent_id`, `date_start`, `date_end`)
VALUES
(1, NULL, '2017-05-01 00:00:00', '2017-05-10 00:00:00'),
(2, 1, '2017-05-01 00:00:00', '2017-05-10 00:00:00'),
(3, NULL, '2017-06-01 00:00:00', '2017-06-10 00:00:00'),
(4, 3, '2017-06-01 00:00:00', '2017-06-03 00:00:00'),
(5, 3, '2017-06-04 00:00:00', '2017-06-06 00:00:00'),
(6, 3, '2017-06-07 00:00:00', '2017-06-10 00:00:00'),
(7, NULL, '2017-07-01 00:00:00', '2017-07-10 00:00:00'),
(8, 7, '2017-07-01 00:00:00', '2017-07-03 00:00:00'),
(9, 7, '2017-07-04 00:00:00', '2017-07-06 00:00:00'),
(10, 7, '2017-07-08 00:00:00', '2017-07-10 00:00:00')
;
MySQL:
select p.id, datediff(p.date_end,p.date_start) pdu, x.du
from pricelist p
inner join (
select
p1.parent_id, sum(datediff(p1.date_end,p1.date_start) + coalesce(datediff(p2.date_start,p1.date_end),0)) du
from (
select parent_id,date_start,date_end
from pricelist
where parent_id IS NOT NULL
) p1
left join (
select parent_id,date_start,date_end
from pricelist
where parent_id IS NOT NULL
) p2 on p1.parent_id = p2.parent_id and p1.date_end < p2.date_start
where datediff(p2.date_start,p1.date_end) = 1 or p2.parent_id is null
group by p1.parent_id
) x on p.id = x.parent_id and datediff(p.date_end,p.date_start) = x.du
where p.parent_id IS NULL
;
看到它在工作:http://rextester.com/JRD47056
T-SQL:
虽然我找不到有效的 MySQL 环境,但我使用了 MSSQL,但避免了任何不能在 MySQL 中使用的分析函数等。但是我依赖 datediff() ,它与 MySQL 中的相同函数略有不同。
TSQL 查询
select p.id, datediff(day,p.date_start,p.date_end) du
from @pricelist p
inner join (
select
p1.parent_id, sum(datediff(day,p1.date_start,p1.date_end) + coalesce(datediff(day,p1.date_end,p2.date_start),0)) du
from (
select parent_id,date_start,date_end
from @pricelist
where parent_id IS NOT NULL
) p1
left join (
select parent_id,date_start,date_end
from @pricelist
where parent_id IS NOT NULL
) p2 on p1.parent_id = p2.parent_id and p1.date_end < p2.date_start
where datediff(day,p1.date_end,p2.date_start) = 1 or p2.parent_id is null
group by p1.parent_id
) x on p.id = x.parent_id and datediff(day,p.date_start,p.date_end) = x.du
where p.parent_id IS NULL
看到它在工作:http://rextester.com/KUK2410
在 MySQL 中,datediff() 只需要 2 个参数,您需要交换字段引用(即最新日期优先)
也许有更简单的方法。我现在能想到的最好的。