[英]SQL query joining a few tables (MySQL)
I need a "little" help with an SQL query (MySQL). 我需要一个SQL查询(MySQL)的“小”帮助。
I have the following tables: 我有以下表格:
COURIERS
table: COURIERS
表:
+------------+ | COURIER_ID | +------------+
DELIVERIES
table: DELIVERIES
表:
+-------------+------------+------------+ | DELIVERY_ID | COURIER_ID | START_DATE | +-------------+------------+------------+
ORDERS
table: ORDERS
表:
+----------+-------------+-------------+ | ORDER_ID | DELIVERY_ID | FINISH_DATE | +----------+-------------+-------------+
COORDINATES
table: COORDINATES
表:
+-------------+-----+-----+------+ | DELIVERY_ID | LAT | LNG | DATE | +-------------+-----+-----+------+
In the real database I have more columns in each table, but for this example the above columns are enough. 在真实数据库中,每个表中有更多列,但对于此示例,上面的列就足够了。
What do I need? 我需要什么?
An SQL query that returns all couriers [ COURIER_ID
], their last delivery [ DELIVERY_ID
] (based on last START_DATE
), the delivery's last coordinate [ LAT
and LNG
] (based on last DATE
) and the remaining orders count (total of orders of the last delivery that have no FINISH_DATE
). 一个SQL查询,它返回所有信使[
COURIER_ID
],它们的最后一次交付[ DELIVERY_ID
](基于最后的START_DATE
),交货的最后一个坐标[ LAT
和LNG
](基于最后一个DATE
)和剩余订单数量(订单总数)最后交货没有FINISH_DATE
)。
A courier can have no deliveries, in this case I want DELIVERY_ID
= NULL, LAT
= NULL and LNG
= NULL in the result. 快递员可以没有交付,在这种情况下,我希望结果中的
DELIVERY_ID
= NULL, LAT
= NULL和LNG
= NULL。
A delivery can have no coordinates, in this case I want LAT
= NULL and LNG
= NULL in the result. 交付可以没有坐标,在这种情况下,我希望结果中的
LAT
= NULL和LNG
= NULL。
What was I able to do? 我能做什么?
SELECT c.`COURIER_ID`,
d.`DELIVERY_ID`,
r.`LAT`,
r.`LNG`,
(SELECT COUNT(DISTINCT `ORDER_ID`)
FROM `ORDERS`
WHERE `DELIVERY_ID` = d.`DELIVERY_ID`
AND `FINISH_DATE` IS NULL) AS REMAINING_ORDERS
FROM `COURIERS` AS c
LEFT JOIN `DELIVERIES` AS d USING (`COURIER_ID`)
LEFT JOIN `COORDINATES` AS r ON r.`DELIVERY_ID` = d.`DELIVERY_ID`
WHERE (CASE WHEN
(SELECT MAX(`START_DATE`)
FROM `DELIVERIES`
WHERE `COURIER_ID` = c.`COURIER_ID`) IS NULL THEN d.`START_DATE` IS NULL ELSE d.`START_DATE` =
(SELECT MAX(`START_DATE`)
FROM `DELIVERIES`
WHERE `COURIER_ID` = c.`COURIER_ID`) END)
AND (CASE WHEN
(SELECT MAX(`DATE`)
FROM `COORDINATES`
WHERE `DELIVERY_ID` = d.`DELIVERY_ID`) IS NULL THEN r.`DATE` IS NULL ELSE r.`DATE` =
(SELECT MAX(`DATE`)
FROM `COORDINATES`
WHERE `DELIVERY_ID` = d.`DELIVERY_ID`) END)
GROUP BY c.`COURIER_ID`
ORDER BY d.`START_DATE` DESC
The problem is that this query is very slow (from 5 to 20 seconds) when I have over 5k COORDINATES
and it does not returns all couriers sometimes. 问题是,当我有超过5k的
COORDINATES
时,这个查询非常慢(从5到20秒)并且它有时不会返回所有信使。
Thank you so much for any solution. 非常感谢您的任何解决方案。
Try this: 尝试这个:
SELECT C.COURIER_ID, D.DELIVERY_ID, D.START_DATE, D.FINISH_DATE,
B.LAT, B.LNG, B.DATE, C.NoOfOrders
FROM COURIERS C
LEFT JOIN ( SELECT *
FROM (SELECT *
FROM DELIVERIES D
ORDER BY D.COURIER_ID, D.START_DATE DESC
) A
GROUP BY COURIER_ID
) AS A ON C.COURIER_ID = A.COURIER_ID
LEFT JOIN ( SELECT *
FROM (SELECT *
FROM COORDINATES CO
ORDER BY CO.DELIVERY_ID, CO.DATE DESC
) B
GROUP BY CO.DELIVERY_ID
) AS B ON A.DELIVERY_ID = B.DELIVERY_ID
LEFT JOIN ( SELECT O.DELIVERY_ID, COUNT(1) NoOfOrders
FROM ORDERS O WHERE FINISH_DATE IS NULL
GROUP BY O.DELIVERY_ID
) AS C ON A.DELIVERY_ID = C.DELIVERY_ID;
I haven't been able to test this query since I don't have a mysql database set up right now, much less with this schema and sample data. 我无法测试此查询,因为我现在没有设置mysql数据库,更不用说这个架构和示例数据了。 But I think this will work for you:
但我认为这对你有用:
select
c.courier_id
, d.delivery_id
, co.lat
, co.lng
, oc.cnt as remaining_orders
from
couriers c
left join (
select
d.delivery_id
, d.courier_id
from
deliveries d
inner join (
select
d.delivery_id
, max(d.start_date) as start_date
from
deliveries d
group by
d.delivery_id
) dmax on dmax.delivery_id = d.delivery_id and dmax.start_date = d.start_date
) d on d.courier_id = c.courier_id
left join (
select
c.delivery_id
, c.lat
, c.lng
from
coordinates c
inner join (
select
c.delivery_id
, max(c.date) as date
from
coordinates c
group by
c.delivery_id
) cmax on cmax.delivery_id = c.delivery_id and cmax.date = c.date
) co on co.delivery_id = d.delivery_id
left join (
select
o.delivery_id
, count(o.order_id) as cnt
from
orders o
where
o.finish_date is null
group by
o.delivery_id
) oc on oc.delivery_id = d.delivery_id
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.