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 张桌子:approvalsactivities

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.

以下是创建和填充approvalsactivities 表的脚本:

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,但它仍然为某些approvalIds 创建多个记录,例如approvalId of 3。它可能看起来很挑剔,但我需要结果集只返回 1 条记录对于每个approvalId,我查询的结果集到底是怎样的。

以上是关于MySQL从父表中查找创建日期在日期之前和之后的子记录的主要内容,如果未能解决你的问题,请参考以下文章

从父表和子表中删除行

对于特定的日期时间,在 [关闭] 之前和之后查找日期时间最近的记录

根据关系表从父表中获取记录 - CoreData

如何从mysql5中的父表中删除数据?

查找每个 ID 的特定日期之前的最大日期和特定日期之后的最小日期 [关闭]

mysql 按日期排序并排序父表