SQL select inside select 使用日期时间列作为参考
SQL select inside select using a datetime column as reference
我有一个 table 看起来像下面的那个:
╔═══════════╦═════════╦═════════════╦═══════════════╦═════════════════════╦═════════════════════╗
║ id_object ║ Name ║ Activity ║ Object_Prefix ║ Start_DateTime ║ End_DateTime ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 213 ║ Junior ║ Fixing ║ G35 ║ 06-11-2020 09:35:06 ║ 06-11-2020 16:39:34 ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 213 ║ Junior ║ End_turn ║ ║ 06-11-2020 17:01:25 ║ ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 213 ║ Richard ║ Auxiliating ║ G35 ║ 06-11-2020 09:35:06 ║ 06-11-2020 16:39:34 ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 213 ║ Richard ║ End_turn ║ ║ 06-11-2020 17:04:07 ║ ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 456 ║ Philip ║ Fixing ║ G08 ║ 02-11-2020 13:35:09 ║ 02:11:2020 21:58:59 ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 456 ║ Philip ║ End_turn ║ ║ 02-11-2020 22:37:51 ║ ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 102 ║ Julia ║ Auxiliating ║ N901 ║ 31-10-2020 20:01:30 ║ 01-11-2020 08:09:41 ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 102 ║ Julia ║ End_turn ║ ║ 01-11-2020 08:13:45 ║ ║
╚═══════════╩═════════╩═════════════╩═══════════════╩═════════════════════╩═════════════════════╝
我一直在尝试 select 将 End turn Times 作为一个新专栏,尽管到目前为止我尝试但没有成功的是:
select
t1.id,
t1.name,
t1.activity,
DATE_FORMAT( t1.Start_DateTime, "%d/%m-%Y %H:%i:%s") as Start,
(Select DATE_FORMAT(t1.Start_DateTime, "%d/%m-%Y %H:%i:%s")
from Activities t2
WHERE t2.Activities = "End_turn" AND t2.id_object = t1.id_object) as end_activity
FROM
Activities t1
WHERE
t1.Object_Prefix != ""
GROUP BY
t.Start_DateTime
我期待的结果是这样的:
但是 end_turn 列总是填充空值。我没弄清楚我在哪里漏掉了它。
如果我没听错,你想为相同的 id_object
和 name
带来“结束回合”行的 start_datetime
。在 MySQL 8.0 中,您可以为此使用 window 函数:
select t.*
from (
select t.*,
min(case when activity = 'End_turn' then start_datetime end)
over(partition by id_object, name) as end_turn
from mytable t
) t
where activity <> 'End_turn'
在早期版本中,替代方法是相关子查询:
select t.*,
(
select min(t1.start_datetime)
from mytable t1
where t1.id_object = t.id_object and t1.name = t.name and t1.activity = 'End_turn'
) as end_turn
from mytable t
where activity <> 'End_turn'
- 您的示例数据与您的查询不一致。
select
t1.id, <--- there is no column named as `id`. Instead it was `id_object`
t1.name,
t1.activity,
DATE_FORMAT( t1.Start_DateTime, "%d/%m-%Y %H:%i:%s") as Start,
(Select DATE_FORMAT(t1.Start_DateTime, "%d/%m-%Y %H:%i:%s")
from Activities t2
WHERE t2.Activities = "End_turn" <---- there is no column named as `activities`. Instead it was `activity`.
AND t2.id_object = t1.id_object) as end_activity
FROM
Activities t1
WHERE
t1.Object_Prefix != ""
GROUP BY
t1.Start_DateTime
- 我已经使用您提供的示例数据尝试了您的查询,我得到了:
Error Code: 1242
Subquery returns more than 1 row
GROUP BY
在 t1.Start_DateTime
列上没有意义,因为它似乎在您的预期结果中清楚地表明您希望他们按 id_product
和 name
.
您在 Start_DateTime
和 End_DateTime
列中的日期格式是 dd-mm-yyyy
而日期相关数据类型的标准 MySQL 日期是 yyyy-mm-dd
.
最后,如果 Start_DateTime 和 End_DateTime 列的数据类型是 date/datetime,我建议这个查询:
SELECT id_object, `Name`,
SUBSTRING_INDEX(GROUP_CONCAT(Activity ORDER BY Start_DateTime ASC),',',1) ac,
MAX(CASE WHEN Object_Prefix <> '' THEN Object_Prefix END) op,
MIN(CASE WHEN activity <> 'End_turn' THEN Start_DateTime END) sdt,
MAX(CASE WHEN activity = 'End_turn' THEN Start_DateTime END) edt
FROM activities
GROUP BY id_object, `Name`;
你可以在这里看到演示:https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=de2af89c39e6636cfb45ee179cfb1461
我有一个 table 看起来像下面的那个:
╔═══════════╦═════════╦═════════════╦═══════════════╦═════════════════════╦═════════════════════╗
║ id_object ║ Name ║ Activity ║ Object_Prefix ║ Start_DateTime ║ End_DateTime ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 213 ║ Junior ║ Fixing ║ G35 ║ 06-11-2020 09:35:06 ║ 06-11-2020 16:39:34 ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 213 ║ Junior ║ End_turn ║ ║ 06-11-2020 17:01:25 ║ ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 213 ║ Richard ║ Auxiliating ║ G35 ║ 06-11-2020 09:35:06 ║ 06-11-2020 16:39:34 ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 213 ║ Richard ║ End_turn ║ ║ 06-11-2020 17:04:07 ║ ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 456 ║ Philip ║ Fixing ║ G08 ║ 02-11-2020 13:35:09 ║ 02:11:2020 21:58:59 ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 456 ║ Philip ║ End_turn ║ ║ 02-11-2020 22:37:51 ║ ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 102 ║ Julia ║ Auxiliating ║ N901 ║ 31-10-2020 20:01:30 ║ 01-11-2020 08:09:41 ║
╠═══════════╬═════════╬═════════════╬═══════════════╬═════════════════════╬═════════════════════╣
║ 102 ║ Julia ║ End_turn ║ ║ 01-11-2020 08:13:45 ║ ║
╚═══════════╩═════════╩═════════════╩═══════════════╩═════════════════════╩═════════════════════╝
我一直在尝试 select 将 End turn Times 作为一个新专栏,尽管到目前为止我尝试但没有成功的是:
select
t1.id,
t1.name,
t1.activity,
DATE_FORMAT( t1.Start_DateTime, "%d/%m-%Y %H:%i:%s") as Start,
(Select DATE_FORMAT(t1.Start_DateTime, "%d/%m-%Y %H:%i:%s")
from Activities t2
WHERE t2.Activities = "End_turn" AND t2.id_object = t1.id_object) as end_activity
FROM
Activities t1
WHERE
t1.Object_Prefix != ""
GROUP BY
t.Start_DateTime
我期待的结果是这样的:
但是 end_turn 列总是填充空值。我没弄清楚我在哪里漏掉了它。
如果我没听错,你想为相同的 id_object
和 name
带来“结束回合”行的 start_datetime
。在 MySQL 8.0 中,您可以为此使用 window 函数:
select t.*
from (
select t.*,
min(case when activity = 'End_turn' then start_datetime end)
over(partition by id_object, name) as end_turn
from mytable t
) t
where activity <> 'End_turn'
在早期版本中,替代方法是相关子查询:
select t.*,
(
select min(t1.start_datetime)
from mytable t1
where t1.id_object = t.id_object and t1.name = t.name and t1.activity = 'End_turn'
) as end_turn
from mytable t
where activity <> 'End_turn'
- 您的示例数据与您的查询不一致。
select
t1.id, <--- there is no column named as `id`. Instead it was `id_object`
t1.name,
t1.activity,
DATE_FORMAT( t1.Start_DateTime, "%d/%m-%Y %H:%i:%s") as Start,
(Select DATE_FORMAT(t1.Start_DateTime, "%d/%m-%Y %H:%i:%s")
from Activities t2
WHERE t2.Activities = "End_turn" <---- there is no column named as `activities`. Instead it was `activity`.
AND t2.id_object = t1.id_object) as end_activity
FROM
Activities t1
WHERE
t1.Object_Prefix != ""
GROUP BY
t1.Start_DateTime
- 我已经使用您提供的示例数据尝试了您的查询,我得到了:
Error Code: 1242 Subquery returns more than 1 row
GROUP BY
在t1.Start_DateTime
列上没有意义,因为它似乎在您的预期结果中清楚地表明您希望他们按id_product
和name
.您在
Start_DateTime
和End_DateTime
列中的日期格式是dd-mm-yyyy
而日期相关数据类型的标准 MySQL 日期是yyyy-mm-dd
.
最后,如果 Start_DateTime 和 End_DateTime 列的数据类型是 date/datetime,我建议这个查询:
SELECT id_object, `Name`,
SUBSTRING_INDEX(GROUP_CONCAT(Activity ORDER BY Start_DateTime ASC),',',1) ac,
MAX(CASE WHEN Object_Prefix <> '' THEN Object_Prefix END) op,
MIN(CASE WHEN activity <> 'End_turn' THEN Start_DateTime END) sdt,
MAX(CASE WHEN activity = 'End_turn' THEN Start_DateTime END) edt
FROM activities
GROUP BY id_object, `Name`;
你可以在这里看到演示:https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=de2af89c39e6636cfb45ee179cfb1461