获取最早日期作为开始日期和最晚日期作为结束日期
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
最后,所有这些都假设您有一个使用 null
和 DateTime
值的合理模式,而不是使用 varchar
的 不合理 模式和空字符串。如果后者确实是您的情况,则架构设计确实 BROKEN 并且您应该 修复它.
这还假设至少 MySql 8.0。如果您使用的是比这更旧的东西,请表示哀悼。 5.7 及更早版本植根于 2006 年的基本设计,并不能真正成为现代数据库平台。
我有一个要求,我需要将最早日期作为开始日期,如果存在最晚日期,那么我需要将其作为结束日期,如果最晚日期为空,这意味着该人仍然活跃,那么我需要将其作为空白。
我在日期字段上使用了最小值和最大值,但如果没有日期,我的最新日期字段不会捕获为空白。
如果你想获得最早的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
最后,所有这些都假设您有一个使用 null
和 DateTime
值的合理模式,而不是使用 varchar
的 不合理 模式和空字符串。如果后者确实是您的情况,则架构设计确实 BROKEN 并且您应该 修复它.
这还假设至少 MySql 8.0。如果您使用的是比这更旧的东西,请表示哀悼。 5.7 及更早版本植根于 2006 年的基本设计,并不能真正成为现代数据库平台。