Reputation: 31
I've to compute a conformity rate and also to keep the total of deliveries, all that for each carrier (transporteur) in SQL. Here is the query I'd tailored to answer that need and it does that successfully, but it's taking about 5 minutes to execute (knowing that "LIVRAISON" table have about 350.000 entries):
SELECT idTrans AS id,
nomTrans,
(COUNT(codeSt)
/ (SELECT COUNT(*)
FROM LIVRAISON
NATURAL JOIN TOURNEE
WHERE idTrans=id
AND DateTrn = DATE_SUB(SYSDATE(), INTERVAL 1 DAY)
)
) AS Taux,
(SELECT COUNT(*)
FROM LIVRAISON
NATURAL JOIN TOURNEE
WHERE idTrans=id
AND DateTrn = DATE_SUB(SYSDATE(), INTERVAL 1 DAY)
) AS Total
FROM LIVRAISON
NATURAL JOIN TOURNEE
NATURAL JOIN TRANSPORTEUR
WHERE "{status_type}"
AND DateTrn = DATE_SUB(SYSDATE(), INTERVAL 1 DAY)
GROUP BY idTrans
(status_type
is a IN condition added in PHP.)
How can I speed up this kind of query (and simplify it by the way) to a few seconds only?
Upvotes: 1
Views: 53
Reputation: 31
I reworked scaisEdge answer (that execute in time but gives rates all equal to 1) to make it usable:
SELECT TOURNEE.idTrans, nomTrans, ( t.tot_typeSt/COUNT(*) ) AS Taux,
COUNT(*) AS Total
FROM LIVRAISON NATURAL JOIN TOURNEE NATURAL JOIN TRANSPORTEUR
INNER JOIN ( SELECT TOURNEE.idTrans, COUNT(codeSt) AS tot_typeSt
FROM LIVRAISON NATURAL JOIN TOURNEE
WHERE {$typeStatut} AND DATE_SUB(SYSDATE(), INTERVAL 1 DAY)
GROUP BY TOURNEE.idTrans ) t ON t.idTrans = TOURNEE.idTrans WHERE DATE_SUB(SYSDATE(), INTERVAL 1 DAY)
GROUP BY idTrans
Thanks, I'll remember using INNER JOIN
for that.
Upvotes: 0
Reputation: 133380
Looking to your code you could avoid the select for column values using a subselect in join eg:
select DISTINCT LIVRAISON.idTrans AS id
, TRANSPORTEUR.nomTrans
, t.my_rate
, t.my_count
FROM LIVRAISON
NATURAL JOIN TOURNEE
NATURAL JOIN TRANSPORTEUR
INNER JOIN (
SELECT idTrans, COUNT(codeSt)/COUNT(*) my_rate, COUNT(*) my_count
FROM LIVRAISON
NATURAL JOIN TOURNEE
WHERE idTrans=id
AND DateTrn = DATE_SUB(SYSDATE(), INTERVAL 1 DAY)
GROUP BY idTrans ) t ON t.idTrans = LIVRAISON.idTrans
WHERE "{status_type}"
AND DateTrn = DATE_SUB(SYSDATE(), INTERVAL 1 DAY)
could be that you can also avoid the IN clause using another inner join
Upvotes: 1