MySQL从父表中查找创建日期在日期之前和之后的子记录
Posted
技术标签:
【中文标题】MySQL从父表中查找创建日期在日期之前和之后的子记录【英文标题】:MySQL find child records where created date is before and after date from parent table 【发布时间】:2020-10-22 01:40:17 【问题描述】:我使用的是 mysql 8.0 版。
我有 2 张桌子:approvals
和 activities
approvals
表与activities
表是一对多的关系,即:一个approvals
记录可以在activities
表中有多条记录。
在approvals
表中创建记录之前和之后都会在activities
表中创建记录。在创建approvals
记录之前创建activities
记录是可以的,因为activities
表实际上绑定到另一个对这个问题不重要的表并且approvals
信息在前更新-approvals
记录创建后的现有activities
表记录。
我要做的是编写一个查询,该查询将显示approvals
记录信息,然后还显示activities
表中在@ 之前和之后创建的记录的记录信息987654338@ 记录已创建。
I have already mocked out the tables and my query on db-fiddle here.
以下是创建和填充approvals
和activities
表的脚本:
CREATE TABLE `approvals` (`id` INTEGER NOT NULL AUTO_INCREMENT, `created` DATETIME, PRIMARY KEY(`id`));
CREATE TABLE `activities` (`id` INTEGER NOT NULL AUTO_INCREMENT, `approvalId` INTEGER, `created` DATETIME, PRIMARY KEY(`id`));
INSERT INTO `approvals` (`created`)
VALUES
('2020-10-04 10:30:05'),
('2020-10-04 10:42:21'),
('2020-10-05 11:24:47'),
('2020-10-06 15:35:35');
INSERT INTO `activities` (`approvalId`, `created`)
VALUES
(1, '2020-09-30 04:24:14'),
(1, '2020-10-01 12:21:05'),
(1, '2020-10-06 12:21:05'),
(1, '2020-10-07 14:29:22'),
(2, '2020-09-28 05:33:10'),
(2, '2020-10-04 09:21:05'),
(2, '2020-10-04 15:27:35'),
(2, '2020-10-07 01:44:12'),
(3, '2020-09-22 04:24:14'),
(3, '2020-10-04 12:21:05'),
(3, '2020-10-06 12:21:05'),
(3, '2020-10-07 14:29:22'),
(4, '2020-09-21 04:24:14'),
(4, '2020-10-04 14:21:05'),
(4, '2020-10-10 12:21:05'),
(4, '2020-10-12 14:29:22');
这是我写的查询:
SELECT `der`.`id` AS `aprvId`,
`oact1`.`id` AS `preActivityId`,
`oact1`.`created` AS `prevActivityCreated`,
`der`.`created` AS `appCreatedDate`,
`oact2`.`id` AS `postActivityId`,
`oact2`.`created` AS `postActivityCreated`
FROM (
SELECT `app`.`id`,
MAX(`act1`.`created`) AS `mxDate`,
`app`.`created`,
'' AS `mnDate`
FROM `approvals` AS `app`
JOIN `activities` AS `act1` ON `act1`.`approvalId` = `app`.`id`
WHERE `act1`.`created` <= `app`.`created`
GROUP BY `app`.`created`, `app`.`id`, `app`.`id`
UNION ALL
SELECT `app`.`id`,
'' AS `mxDate`,
`app`.`created`,
MIN(`act1`.`created`) AS `mnDate`
FROM `approvals` AS `app`
JOIN `activities` AS `act1` ON `act1`.`approvalId` = `app`.`id`
WHERE `act1`.`created` >= `app`.`created`
GROUP BY `app`.`created`, `app`.`id`, `app`.`id`
) AS `der`
JOIN `activities` AS `oact1` ON `oact1`.`approvalId` = `der`.`id`
JOIN `activities` AS `oact2` ON `oact2`.`approvalId` = `der`.`id`
GROUP BY `der`.`id`, `oact1`.`id`, `oact2`.`id`, `der`.`created`
HAVING `prevActivityCreated` = MAX(`der`.`mxDate`) AND `postActivityCreated` = MAX(`der`.`mnDate`)
这是我的查询的输出(同样,这个查询有效,这是我需要的输出):
| aprvId | appCreatedDate | preActivityId | prevActivityCreated | postActivityId | postActivityCreated |
| ------ | ------------------- | ------------- | ------------------- | -------------- | ------------------- |
| 1 | 2020-10-04 10:30:05 | 2 | 2020-10-01 12:21:05 | 3 | 2020-10-06 12:21:05 |
| 2 | 2020-10-04 10:42:21 | 6 | 2020-10-04 09:21:05 | 7 | 2020-10-04 15:27:35 |
| 3 | 2020-10-05 11:24:47 | 10 | 2020-10-04 12:21:05 | 11 | 2020-10-06 12:21:05 |
| 4 | 2020-10-06 15:35:35 | 14 | 2020-10-04 14:21:05 | 15 | 2020-10-10 12:21:05 |
它为我提供了我正在寻找的数据,我的问题是:有没有更好、更清洁或更有效的方法来获取这些信息?
【问题讨论】:
【参考方案1】:嗯。 . .我认为这样做是:
select aa.*, ac_prev.*, ac_next.*
from (select ap.id, ap.created,
max(case when ac.created < ap.created then ac.created end) as prev_created,
min(case when ac.created > ap.created then ac.created end) as next_created
from approvals ap cross join
activities ac
group by ap.id, ap.created
) aa left join
activities ac_prev
on ac_prev.created = aa.prev_created left join
activities ac_next
on ac_next.created = aa.next_created;
Here 是一个 dbfiddle。
【讨论】:
该查询已关闭,但在只应返回 4 行时返回 6 行。您查询的结果集与我的结果集相似,但略有不同。不过还是谢谢。 @GharbadTheWeak 。 . .这将匹配活动与批准放在同一行,这似乎很符合问题的精神。 true,但它仍然为某些approvalId
s 创建多个记录,例如approvalId
of 3。它可能看起来很挑剔,但我需要结果集只返回 1 条记录对于每个approvalId
,我查询的结果集到底是怎样的。以上是关于MySQL从父表中查找创建日期在日期之前和之后的子记录的主要内容,如果未能解决你的问题,请参考以下文章
对于特定的日期时间,在 [关闭] 之前和之后查找日期时间最近的记录