2013-10-21 74 views
0

我試圖讓潛在客戶的名單與他們的訂單歷史記錄(LTV)MySQL的左連接以一段時間

的和無沿的,這個查詢負載的順序在第二下。隨着order by和查詢超過90秒。

SELECT a.customerid,a.firstname,a.lastname,Orders.ltv 
    FROM customers a 
    LEFT JOIN (
     SELECT customerid, 
       SUM(amount) as ltv 
     FROM orders 
     GROUP BY customerid) Orders 
    ON Orders.customerid=a.customerid 
ORDER BY 
    Orders.ltv DESC 
LIMIT 0,10 

任何想法如何可以加快?

編輯:我想我清理查詢有點太多。這個版本的查詢實際上要複雜一點。其他數據從客戶表中選擇,也可以進行排序。

+2

我的猜測是你正在對沒有合適索引的表運行查詢。我的猜測是你也不需要子選擇。你可以運行'SHOW CREATE TABLE customers'和'SHOW CREATE TABLE orders'並把結果放在你的問題中嗎?實際上,在查看您的查詢時,我不明白爲什麼您加入了所有正弦表中的客戶表,您只能從中獲得客戶訂單(該訂單表中已存在相同的值。 –

+0

@ user2864740:它來自子查詢,沒有索引;) – Wrikken

+0

@jwatkins你根本不需要做子選擇。您可以計算總和而無需再次選擇。 –

回答

4

沒有實際的架構是有點很難知道數據是如何相關的,但我想這個查詢應該是等價的,更高性能:

SELECT a.customerid, coalesce(sum(o.amount), 0) TotalLtv FROM customers a 
LEFT JOIN orders o ON a.customerid = o.cusomterid 
GROUP BY a.customerid 
ORDER BY TotalLtv DESC 
LIMIT 10 

的​​3210將確保您返回0爲客戶無命令。

由於@ypercube讓我注意到,amount上的索引也無濟於事。你可以給它一個嘗試:

ALTER TABLE orders ADD INDEX(customer, amount) 

你的問題更新

後如果需要添加更多的字段在SELECT子句中功能取決於a.customerid你可以使用非標準的MySQL group by條款。這將導致比分組更好的性能a.customerid, a.firstname, a.lastname

SELECT a.customerid, a.firstname, a.lastname, coalesce(sum(o.amount), 0) TotalLtv 
FROM customers a 
LEFT JOIN orders o ON a.customerid = o.cusomterid 
GROUP BY a.customerid 
ORDER BY TotalLtv DESC 
LIMIT 10 
+1

'(金額)'上的索引根本無濟於事。 '(customerid,amount)'的索引可能。 –

+0

哎呀,你顯然是對的。而你提出的那個甚至根本不會有太大的幫助,但它值得嘗試。 –

+0

即使沒有索引,這也是一個巨大的進步。謝謝! – Michael

2

這裏有幾件事。首先它並不表示您需要加入customers表格,因爲您僅將它用於customerid,該表格已存在於orders表格中。如果您有超過10個客戶ID和相應的金額,那麼您甚至不需要查看客戶ID列表,這些客戶ID不包含客戶使用LEFT JOIN獲得的金額。因此,您應該能夠將您的查詢減少到:

SELECT customerid, SUM(amount) AS ltv 
FROM orders 
GROUP BY customerid 
ORDER BY ltv DESC LIMIT 0,10 

您需要customerid上的索引。不幸的是,排序是在一個計算的領域,所以從這一點來說,你可以做很多事情來加快這一進程。

我看到更新的問題。因爲你需要從客戶的附加字段,我將修改我的答案,包括客戶表

SELECT c.customerid, c.firstname, c.lastname, coalesce(o.ltv, 0) AS total 
FROM customers AS c 
LEFT JOIN (
    SELECT customerid, SUM(amount) as ltv 
    FROM orders 
    GROUP BY customerid 
    ORDER BY ltv DESC LIMIT 0,10) AS o 
ON c.customerid = o.customerid 

請注意,我在子選擇的表連接,你是在原來的查詢做,但是我已經完成子選擇表上的排序和限制,因此您無需在訂單表上排序所有記錄,而無需任何條目。

+0

假設客戶的訂單總和爲「0」可以省去結果。 – dognose

0

兩件事。首先,不要使用內部查詢。 MySQL確實允許在投影別名上使用ORDER BY。其次,你應該通過在組合鍵(customerid,amount)上有一個B-TREE索引來獲得相當大的改進。然後,引擎將能夠通過索引的簡單遍歷來執行此查詢,而無需獲取任何行數據。