获取最早日期作为开始日期和最晚日期作为结束日期

Get earliest date as Start date and latest date as end date

我有一个要求,我需要将最早日期作为开始日期,如果存在最晚日期,那么我需要将其作为结束日期,如果最晚日期为空,这意味着该人仍然活跃,那么我需要将其作为空白。

我在日期字段上使用了最小值和最大值,但如果没有日期,我的最新日期字段不会捕获为空白。

如果你想获得最早的start_date,通过ID。还要带上 End_date 字段中的任何内容——无论它是 NULL 还是有日期。然后您可以先按 ID 分组(在您给出的示例中这不是唯一的),然后在 start_date 上使用 MIN()。然后你获取这些值属于哪一行,从而得到 End_date。这行得通,但如果您有多个具有相同 ID 的开始日期,这会使事情变得复杂 - 在这种情况下,我们需要更多示例数据以及对它应该如何工作的更多解释。但是,这里是:

Fiddle: https://www.db-fiddle.com/f/o2NyDpAc76TLYdmGFGHqag/3

CREATE TABLE my_table (
  ID int,
  Start_Date date,
  End_date date null
);
INSERT INTO my_table (ID,Start_Date, End_date) 
VALUES 
(1,'2021-01-01', '2022-04-05'),
(1,'2022-01-01', '2022-04-02'),
(2,'2022-07-01', '2022-05-07'),
(2,'2022-01-01', null);

SELECT a.*
FROM my_table a
join (SELECT 
ID,
MIN(my_table.Start_date) as 'Start_date'
FROM my_table
GROUP BY ID) jn
on a.ID=jn.ID and a.Start_date=jn.Start_date

来源table:

ID Start_Date End_date
1 '2021-01-01' '2022-04-05'
1 '2022-01-01' 2022-04-02
2 '2022-07-01' '2022-05-07'
2 '2022-01-01' NULL

结果table:

ID Start_Date End_date
1 '2021-01-01' '2022-04-05'
2 '2022-01-01' NULL

这可能有效:

SELECT ID, MIN(start_date) Start_Date, 
    NULLIF(MAX(COALESCE(end_date,'29991231')), '29991231') End_Date
FROM MyTable
GROUP BY ID

在这里查看它的工作原理:

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=5febc25e9c79840fe6aa2e55d77cf5d0

至少它 似乎 根据可用的样本数据给出正确的结果。但是,如果开始日期较早的记录有 null 结束日期,而开始日期较晚的记录确实有结束日期,这仍会显示 null。这很可能永远不会发生在真实数据中,但真实数据往往会变得混乱,即使它不应该如此。


要真正正确地执行此操作,您需要找到具有最晚开始日期的 整行 ,然后查看该行的结束日期值 幸运的是,我们有一个很好的方法来计算行数:row_number() 窗口函数:

SELECT ID, Start_Date, End_Date
FROM (
    SELECT ID, Start_Date, End_Date, 
        row_number() over (PARTITION BY ID ORDER BY Start_Date DESC) rn
    FROM MyTable
) t0
WHERE rn=1

但这只是解决方案的一部分。现在应该总是有正确的 End_Date,但通常会有错误的 Start_Date。我们可以像这样更新它以修复该错误:

SELECT ID, (SELECT MIN(Start_Date) FROM MyTable t WHERE t.ID=t0.ID) Start_Date, End_Date
FROM (
    SELECT ID, Start_Date, End_Date, 
        row_number() over (PARTITION BY ID ORDER BY Start_Date DESC) rn
    FROM MyTable
) t0
WHERE rn=1

现在我们将总是得到正确的结果。

在这里查看它的工作原理:

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=4b7d4cba4849eee9ba3bf978cebfc3bf


最后,所有这些都假设您有一个使用 nullDateTime 值的合理模式,而不是使用 varchar 不合理 模式和空字符串。如果后者确实是您的情况,则架构设计确实 BROKEN 并且您应该 修复它.

这还假设至少 MySql 8.0。如果您使用的是比这更旧的东西,请表示哀悼。 5.7 及更早版本植根于 2006 年的基本设计,并不能真正成为现代数据库平台。