在 SQL 中,如果满足条件,我如何用 child 记录过滤 parent

In SQL, how do I filter a parent with its child records if either satisfies a condition

我有以下 table 作为示例。对于 parent 和 child 记录,我只想检索 ScheduleDate 小于 2022-01-03(2022 年 1 月 3 日)的记录,但我只想要整个家庭(parents 和 children 在一起)。使用这组记录,结果应该 return 只有记录 1 到 9。 ScheduleId 12不满足条件,与10、13有关系。10与11有关系。

DROP TABLE IF EXISTS #MySchedule;
CREATE TABLE #MySchedule (ScheduleId INT, ParentScheduleId INT, ScheduleDate DATETIME2);

INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (1,NULL,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (2,NULL,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (3,2,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (4,2,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (5,4,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (6,NULL,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (7,6,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (8,6,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (9,8,'2022-01-02');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (10,NULL,'2022-01-02');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (11,10,'2022-01-02');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (12,10,'2022-01-03');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (13,12,'2022-01-02');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (14,NULL,'2022-01-03');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (15,NULL,'2022-01-03');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (16,NULL,'2022-01-04');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (17,16,'2022-01-04');

我必须说你的问题定义有点含糊。在编写此解决方案时,我不得不假设您希望看到一个没有 children 的家庭 ScheduleDate 大于 2022-01 -03。如果这不是您要寻找的解决方案,请澄清您的问题定义。 我们开始吧:D

DROP TABLE IF EXISTS #MySchedule;
CREATE TABLE #MySchedule (ScheduleId INT, ParentScheduleId INT, ScheduleDate DATETIME2);

INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (1,NULL,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (2,NULL,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (3,2,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (4,2,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (5,4,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (6,NULL,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (7,6,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (8,6,'2022-01-01');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (9,8,'2022-01-02');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (10,NULL,'2022-01-02');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (11,10,'2022-01-02');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (12,10,'2022-01-03');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (13,12,'2022-01-02');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (14,NULL,'2022-01-03');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (15,NULL,'2022-01-03');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (16,NULL,'2022-01-04');
INSERT #MySchedule (ScheduleId, ParentScheduleId, ScheduleDate) VALUES  (17,16,'2022-01-04');

DECLARE @date DATETIME2 = '2022-01-03';

SELECT COUNT(1) FROM #MySchedule;

WITH src AS (
    /* get all ultimate parents */
    SELECT ScheduleId,
           [ParentScheduleId],
           ScheduleDate,
           ScheduleId [ultimate_ParentScheduleId]
    FROM #MySchedule shd
    WHERE shd.ParentScheduleId  IS NULL
        UNION ALL
    SELECT shd.ScheduleId,
           shd.ParentScheduleId,
           shd.ScheduleDate,
           src.ultimate_ParentScheduleId
    FROM #MySchedule shd
        JOIN src
            ON shd.ParentScheduleId = src.ScheduleId
)
SELECT
    src.ultimate_ParentScheduleId,
    src.ParentScheduleId,
    src.ScheduleId,
    src.ScheduleDate
FROM src
    JOIN (
        SELECT src.ultimate_ParentScheduleId
        FROM src
        GROUP BY src.ultimate_ParentScheduleId
        HAVING MAX(src.ScheduleDate) < @date
    ) gp
        ON gp.ultimate_ParentScheduleId = src.ultimate_ParentScheduleId
ORDER BY src.ultimate_ParentScheduleId, COALESCE(src.ParentScheduleId, src.ScheduleId), src.ScheduleId
;