MYSQL - Select 行匹配事件代码并立即处理下一行并计算时间日期差异
MYSQL - Select rows matching event code and imediate next row and calculate time date difference
所以这是 table
ID Date Event
1547 2013-05-09 16:26:02 PA
1547 2013-05-15 13:59:23 TA
1547 2013-05-21 10:16:56 EA
1547 2013-05-21 10:17:27 PM
1547 2014-01-16 11:42:12 IH
1547 2014-01-16 11:42:13 RP
1547 2014-01-21 10:01:18 MP <-
1547 2014-12-05 14:32:21 RE <-
1547 2014-12-05 14:34:24 RE
1666 2013-05-29 11:26:38 PA
1666 2013-06-04 13:38:42 TA
1666 2013-06-05 14:16:13 EA
1666 2013-08-21 10:07:08 PR
1666 2013-08-21 10:38:51 TR
1666 2013-08-21 10:38:52 MP <-
1666 2013-10-07 16:26:46 PM <-
1666 2013-10-09 14:38:51 TM
1666 2013-10-09 14:38:52 EP
1666 2013-10-25 10:29:01 IH
1666 2013-12-13 08:52:41 IH
1666 2013-12-13 08:52:43 RP
1666 2014-01-21 09:55:10 MP <-
1666 2014-05-05 15:52:34 AB <-
1666 2014-05-07 14:55:58 RD
1692 2013-06-10 14:17:17 PA
1692 2013-06-10 14:17:53 TA
1692 2013-06-10 15:01:08 EA
1692 2013-08-21 10:04:39 PR
1692 2013-08-21 10:37:38 TR
1692 2013-08-21 10:37:39 ER
1692 2013-09-26 08:33:48 PM
1692 2013-09-26 16:32:46 TM
1692 2013-09-26 16:32:47 EP
1692 2013-10-11 09:21:26 IH
1692 2013-12-19 15:29:20 IV
1692 2013-12-19 15:29:21 RP
1692 2013-12-19 15:33:19 MP <-
1692 2014-01-21 11:05:46 FX <-
1692 2014-01-22 10:16:27 RE
我想 select 每个 ID 的第一个“MP”事件,下一个立即发生并计算天数差异。
结果应该是:
ID Date DaystoNextEVENT
1547 2014-01-21 10:01:18 318
1666 2013-08-21 10:38:52 47
1666 2014-01-21 09:55:10 104
1692 2013-12-19 15:33:19 33
我曾尝试使用限制,但总是无法限制具有匹配日期来源的同一 ID 的下一行。
对于版本 8+:
SELECT id,
`date`,
DATEDIFF(LEAD(`date`) OVER (PARTITION BY id ORDER BY `date`), -- next date
`date` -- the date of MP
) DaystoNextEVENT
FROM table t1
WHERE event = 'MP'
AND NOT EXISTS ( SELECT NULL -- check that there is no MP earlier
FROM table t2
WHERE t1.id = t2.id
AND t1.`date` > t2.`date`
AND t2.event = 'MP' );
版本 5.x:
SELECT t1.id,
t1.`date`,
DATEDIFF(t2.`date`, t1.`date`) DaystoNextEVENT
FROM table t1 -- row with MP
JOIN table t2 ON t1.id = t2.id -- next row
AND t1.`date` < t2.`date`
WHERE t1.event = 'MP'
AND NOT EXISTS ( SELECT NULL -- check that there is no MP earlier
FROM table t3
WHERE t1.id = t3.id
AND t1.`date` > t3.`date`
AND t3.event = 'MP' )
AND NOT EXISTS ( SELECT NULL -- check that there is no a row
FROM table t4 -- between rows from tables t1 and t2
WHERE t1.id = t4.id
AND t1.`date` < t4.`date`
AND t4.`date` < t2.`date` );
我们可以在 sub-query 中使用光标,使用 order by day desc
我们可以反转排序顺序,从而给出下一个事件的日期。如果它是相同的 ID,我们将在查询中 return 它。
SET @quot='';
SET @id=0;
select
id,
day,
lag_day,
event,
case when id=lag_id then
datediff(lag_day,day) end
as days_to_next
from
(select
@id lag_id,
@id:=id id,
@quot lag_day,
@quot:=day day,
event
from
events
order by
id ,
day desc) e
where event ='MP'
order by
id,
day;
id | day | lag_day | event | days_to_next
---: | :------------------ | :------------------ | :---- | -----------:
1547 | 2014-01-21 10:01:18 | 2014-12-05 14:32:21 | MP | 318
1666 | 2013-08-21 10:38:52 | 2013-10-07 16:26:46 | MP | 47
1666 | 2014-01-21 09:55:10 | 2014-05-05 15:52:34 | MP | 104
1692 | 2013-12-19 15:33:19 | 2014-01-21 11:05:46 | MP | 33
db<>fiddle here
所以这是 table
ID Date Event
1547 2013-05-09 16:26:02 PA
1547 2013-05-15 13:59:23 TA
1547 2013-05-21 10:16:56 EA
1547 2013-05-21 10:17:27 PM
1547 2014-01-16 11:42:12 IH
1547 2014-01-16 11:42:13 RP
1547 2014-01-21 10:01:18 MP <-
1547 2014-12-05 14:32:21 RE <-
1547 2014-12-05 14:34:24 RE
1666 2013-05-29 11:26:38 PA
1666 2013-06-04 13:38:42 TA
1666 2013-06-05 14:16:13 EA
1666 2013-08-21 10:07:08 PR
1666 2013-08-21 10:38:51 TR
1666 2013-08-21 10:38:52 MP <-
1666 2013-10-07 16:26:46 PM <-
1666 2013-10-09 14:38:51 TM
1666 2013-10-09 14:38:52 EP
1666 2013-10-25 10:29:01 IH
1666 2013-12-13 08:52:41 IH
1666 2013-12-13 08:52:43 RP
1666 2014-01-21 09:55:10 MP <-
1666 2014-05-05 15:52:34 AB <-
1666 2014-05-07 14:55:58 RD
1692 2013-06-10 14:17:17 PA
1692 2013-06-10 14:17:53 TA
1692 2013-06-10 15:01:08 EA
1692 2013-08-21 10:04:39 PR
1692 2013-08-21 10:37:38 TR
1692 2013-08-21 10:37:39 ER
1692 2013-09-26 08:33:48 PM
1692 2013-09-26 16:32:46 TM
1692 2013-09-26 16:32:47 EP
1692 2013-10-11 09:21:26 IH
1692 2013-12-19 15:29:20 IV
1692 2013-12-19 15:29:21 RP
1692 2013-12-19 15:33:19 MP <-
1692 2014-01-21 11:05:46 FX <-
1692 2014-01-22 10:16:27 RE
我想 select 每个 ID 的第一个“MP”事件,下一个立即发生并计算天数差异。
结果应该是:
ID Date DaystoNextEVENT
1547 2014-01-21 10:01:18 318
1666 2013-08-21 10:38:52 47
1666 2014-01-21 09:55:10 104
1692 2013-12-19 15:33:19 33
我曾尝试使用限制,但总是无法限制具有匹配日期来源的同一 ID 的下一行。
对于版本 8+:
SELECT id,
`date`,
DATEDIFF(LEAD(`date`) OVER (PARTITION BY id ORDER BY `date`), -- next date
`date` -- the date of MP
) DaystoNextEVENT
FROM table t1
WHERE event = 'MP'
AND NOT EXISTS ( SELECT NULL -- check that there is no MP earlier
FROM table t2
WHERE t1.id = t2.id
AND t1.`date` > t2.`date`
AND t2.event = 'MP' );
版本 5.x:
SELECT t1.id,
t1.`date`,
DATEDIFF(t2.`date`, t1.`date`) DaystoNextEVENT
FROM table t1 -- row with MP
JOIN table t2 ON t1.id = t2.id -- next row
AND t1.`date` < t2.`date`
WHERE t1.event = 'MP'
AND NOT EXISTS ( SELECT NULL -- check that there is no MP earlier
FROM table t3
WHERE t1.id = t3.id
AND t1.`date` > t3.`date`
AND t3.event = 'MP' )
AND NOT EXISTS ( SELECT NULL -- check that there is no a row
FROM table t4 -- between rows from tables t1 and t2
WHERE t1.id = t4.id
AND t1.`date` < t4.`date`
AND t4.`date` < t2.`date` );
我们可以在 sub-query 中使用光标,使用 order by day desc
我们可以反转排序顺序,从而给出下一个事件的日期。如果它是相同的 ID,我们将在查询中 return 它。
SET @quot=''; SET @id=0; select id, day, lag_day, event, case when id=lag_id then datediff(lag_day,day) end as days_to_next from (select @id lag_id, @id:=id id, @quot lag_day, @quot:=day day, event from events order by id , day desc) e where event ='MP' order by id, day;
id | day | lag_day | event | days_to_next ---: | :------------------ | :------------------ | :---- | -----------: 1547 | 2014-01-21 10:01:18 | 2014-12-05 14:32:21 | MP | 318 1666 | 2013-08-21 10:38:52 | 2013-10-07 16:26:46 | MP | 47 1666 | 2014-01-21 09:55:10 | 2014-05-05 15:52:34 | MP | 104 1692 | 2013-12-19 15:33:19 | 2014-01-21 11:05:46 | MP | 33
db<>fiddle here