Mysql 正在寻找正确的查询
我有一个名为Mysql 正在寻找正确的查询,mysql,sql,laravel,Mysql,Sql,Laravel,我有一个名为document\u histories的表。我的表格的一个示例: id | assembly_order_id | document_type | document_year | document_number | document_date | created_at | updated_at 2839 | 1287 | ub | 2019 | 928 | 2019-03
document\u histories
的表。我的表格的一个示例:
id | assembly_order_id | document_type | document_year | document_number | document_date | created_at | updated_at
2839 | 1287 | ub | 2019 | 928 | 2019-03-18 | 2019-03-18 14:00:27 | 2019-03-18 14:00:27
2861 | 1287 | us | 2019 | 881 | 2019-03-19 | 2019-03-19 16:31:06 | 2019-03-19 16:31:06
2862 | 1287 | us | 2019 | 882 | 2019-03-20 | 2019-03-20 16:39:06 | 2019-03-20 16:39:06
2896 | 1287 | ul | 2019 | 932 | 2019-03-25 | 2019-03-25 10:55:10 | 2019-03-25 10:55:10
我想做的是列出从一个文档到另一个文档所花费的时间。
例如:
#2839
是我们的出发点(ub)。文件日期为2019-03-18。现在,我需要具有相同组装顺序\u id
且文档类型为us
的行的最低文档\u日期
所以我们有这样的东西:
id | assembly_order_id | document_type | document_year | document_number | document_date | created_at | updated_at | *date_diff*
2839 | 1287 | ub | 2019 | 928 | 2019-03-18 | 2019-03-18 14:00:27 | 2019-03-18 14:00:27 | *1* (2019-03-19 - 2019-03-18)
这只是1个差异,但我还需要us
(最低日期)和ul
(最新/最高日期)之间的时差,以及ub
(最低日期)和ul
(最新/最高日期)之间的时差
我尝试了以下查询,但这无法完全正常工作,因为它在“time\u until\u assembly”、“assembly\u time”和“total\u delivery\u time”列中返回了大量空值:
SELECT
ub.*,
@time_until_assembly:= DATEDIFF((SELECT us.document_date FROM document_histories us WHERE us.document_type = 'us' AND us.assembly_order_id = ub.assembly_order_id LIMIT 1), ub.document_date) AS time_until_assembly,
DATEDIFF((SELECT ul.document_date FROM document_histories ul WHERE ul.document_type = 'ul' AND ul.assembly_order_id = ub.assembly_order_id LIMIT 1), @time_until_assembly) AS assembly_time,
DATEDIFF((SELECT dl.document_date FROM document_histories dl WHERE dl.document_type = 'ul' AND dl.assembly_order_id = ub.assembly_order_id LIMIT 1), ub.document_date) AS total_delivery_time
FROM
document_histories ub
WHERE
ub.document_type = 'ub'
由于输出不正确,我尝试了另一种方法:
SELECT
ub.*,
ub.document_date as ub_date,
us.document_date as us_date,
ul.document_date as ul_date,
DATEDIFF(ul.document_date, ub.document_date) as total_days_delivery,
DATEDIFF(ul.document_date, us.document_date) as total_days_assembly,
DATEDIFF(us.document_date, ub.document_date) as total_days_order
FROM
document_histories ub, document_histories us, document_histories ul
WHERE
ub.document_type = 'ub' AND
us.document_type = 'us' AND
ul.document_type = 'ul' AND
us.assembly_order_id = ub.assembly_order_id AND
ul.assembly_order_id = ub.assembly_order_id
ORDER BY
ub.document_date ASC,
us.document_date ASC,
ul.document_date DESC
但这将返回一个包含重复值的列表,该列表具有不同的总值。尝试使用外部联接:
SELECT
ub.*,
ub.document_date as ub_date,
us.document_date as us_date,
ul.document_date as ul_date,
DATEDIFF(ul.document_date, ub.document_date) as total_days_delivery,
DATEDIFF(ul.document_date, us.document_date) as total_days_assembly,
DATEDIFF(us.document_date, ub.document_date) as total_days_order
FROM
document_histories ub
LEFT JOIN document_histories us ON us.assembly_order_id = ub.assembly_order_id AND us.document_type = 'us'
LEFT JOIN document_histories ul ON ul.assembly_order_id = ub.assembly_order_id AND ul.document_type = 'ul'
WHERE
ub.document_type = 'ub'
编辑以进行聚合:
SELECT
ub.*,
ub.document_date as ub_date,
us.document_date as us_date,
ul.document_date as ul_date,
DATEDIFF(ul.document_date, ub.document_date) as total_days_delivery,
DATEDIFF(ul.document_date, us.document_date) as total_days_assembly,
DATEDIFF(us.document_date, ub.document_date) as total_days_order
FROM
document_histories ub
LEFT JOIN (
SELECT
assembly_order_id,document_date
FROM document_histories
WHERE
document_type = 'us'
ORDER BY
document_date ASC -- Change ASC/DESC respectively
LIMIT 1) us ON us.assembly_order_id = ub.assembly_order_id
LEFT JOIN (
SELECT
assembly_order_id,document_date
FROM document_histories
WHERE
document_type = 'ul'
ORDER BY
document_date DESC -- Change ASC/DESC respectively
LIMIT 1) ul ON ul.assembly_order_id = ub.assembly_order_id
WHERE
ub.document_type = 'ub'
基于以上答案,我提出以下问题以完全实现我的目标:
SELECT
ub.id, ub.assembly_order_id, ub.document_type, ub.document_year, ub.document_number, ub.document_date as order_date, ul.document_date as delivery_date, us.document_date as assembly_date, DATEDIFF(ul.document_date, ub.document_date) as delivery_days, DATEDIFF(ul.document_date, us.document_date) as assembly_days
FROM
`document_histories` ub
INNER JOIN (
SELECT
assembly_order_id, document_date
FROM
`document_histories`
WHERE document_type = 'ul'
GROUP BY assembly_order_id
ORDER BY document_date DESC
) ul ON ul.assembly_order_id = ub.assembly_order_id
LEFT JOIN (
SELECT
assembly_order_id, document_date
FROM
document_histories
WHERE document_type = 'us'
GROUP BY assembly_order_id
ORDER BY document_date ASC
) us ON us.assembly_order_id = ub.assembly_order_id
WHERE
ub.document_type = 'ub'
ORDER BY `delivery_days` DESC
非常感谢您今天的提示:切换到现代的显式JOIN
语法。更容易编写(没有错误),更容易阅读(和维护),并且在需要时更容易转换为外部连接。你能推荐一个好的教程/视频来解释这些吗?我一直在网上浏览,读了很多关于所有不同连接类型的页面,但我不知道如何在这种情况下正确地使用它们。特别是因为我需要的其他行都在同一个表中。使用您编辑的代码,我在us\u date、ul\u date en total列中得到了很多空值,“左连接”是要使用的右连接吗?您可以使用内部连接来仅获得包含所有3种文档类型的结果-ub、us、ul