2010-08-16 82 views
4

我無法在Mysql中查詢子查詢。很簡單的人都ok,最教程我發現很少去超越典型:不能得到頭輪子查詢

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2); 

什麼我試圖拔出我的數據庫是下面(我會盡我所能來解釋這一點沒有任何背景在我們的數據庫中):

檢索屬於上個月(在一列中)特定代表和總消費金額的客戶列表以及在其他列中到目前爲止所花費的金額。

至於結果,這看起來大致如下:我使用以獲取數據的第一部分

ID | NAME | PREV MONTH | CUR MONTH 
1 | foobar | £2300  | £1200 
2 | barfoo | £1240  | £500 

查詢如下:

SELECT c.id,c.name, SUM(co.invoicetotal) as total 
FROM customers as c 
JOIN customerorders as co on co.customer_id = c.id 
WHERE c.salesrep_id = 24 
AND co.orderdate BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE() 
GROUP by c.id 
order by total desc 

的DATE_SUB可以被替換實際日期,因爲php變量最終會到達這裏。作爲一個例子,這只是給我有效的數據。

這給我,例如:

ID | NAME | TOTAL 
1 | foobar | £2300  
2 | barfoo | £1240 

所以,理想情況下,我的子查詢應該是這樣完全相同的查詢,但隨着日期改變。我不斷收到#1242 - Subquery returns more than 1 row錯誤。

有什麼建議或建議嗎?

在此先感謝。 羅布

回答

5
SELECT c.id, c.name, 
     (
     SELECT SUM(co.invoicetotal) 
     FROM customerorders co 
     WHERE co.customer_id = c.id 
       AND co.orderdate BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE() 
     ) AS prev_month, 
     (
     SELECT SUM(co.invoicetotal) 
     FROM customerorders co 
     WHERE co.customer_id = c.id 
       AND co.orderdate BETWEEN CURDATE() AND CURDATE() + INTERVAL 1 MONTHS 
     ) AS cur_month, 
FROM customers as c 
WHERE c.salesrep_id = 24 
ORDER BY 
     prev_month DESC 
+0

你回來了?我們完蛋了! – 2010-08-16 16:24:31

+0

MWA-HA-HA !!!!!! – Quassnoi 2010-08-16 16:29:25

+0

這個作品現場感謝,非常感謝。感謝其他人對你的貢獻。儘管我很可能會使用Quassnoi的查詢來達到我的目的,但我仍然會通過所有答案來幫助我學習,歡呼。 – prevailrob 2010-08-17 08:04:31

1

你的錯誤是因爲其原因是:

WHERE column1 = (SELECT column1 FROM t2) 

t2.column1正在恢復不是一個結果多,但由於子查詢之前等於運算 - 只一個能值被接受。

所以,你要麼需要將其更改爲:

WHERE column1 IN (SELECT column1 FROM t2) 

...接受多個值。或更改子查詢只返回一個變量 - 本例中爲整個返回表中最高t2.column1值:

WHERE column1 = (SELECT MAX(column1) FROM t2) 

這一切都取決於你想獲得什麼樣的數據。

0

OMG小馬對你爲什麼得到那個錯誤是正確的。用於比較的子查詢必須始終返回單個值。

我的猜測是,您需要創建兩個子查詢(一個用於prev,另一個用於curr)並通過用戶ID加入它們。事情是這樣的:

SELECT prev.id,prev.name, prev.total, curr.total 
FROM 
(
SELECT c.id,c.name, SUM(co.invoicetotal) as total 
FROM customers as c JOIN customerorders as co on co.customer_id = c.id 
WHERE c.salesrep_id = 24 
AND co.orderdate BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE() 
GROUP by c.id ORDER BY total desc 
) as prev 
JOIN 
(
SELECT c.id,c.name, SUM(co.invoicetotal) as total 
FROM customers as c JOIN customerorders as co on co.customer_id = c.id 
WHERE c.salesrep_id = 24 
AND co.orderdate > CURDATE() 
GROUP by c.id ORDER BY total desc 
) as curr 
ON prev.id=curr.id 
1

我離開了日期計算,因爲你正在生成,從代碼:

SELECT c.id,c.name, 
    SUM(case when co.orderdate >= @LastMonthStartDate and co.orderdate < @CurrentMonthStartDate then co.invoicetotal else 0 end) as LastMonthTotal, 
    SUM(case when co.orderdate between @CurrentMonthStartDate and CURDATE() then co.invoicetotal else 0 end) as CurrentMonthTotalToDate 
FROM customers as c 
JOIN customerorders as co on co.customer_id = c.id 
WHERE c.salesrep_id = 24 
    AND co.orderdate BETWEEN @LastMonthStartDate AND CURDATE() --remove this if you want customers that did not order in the last 2 months 
GROUP by c.id 
order by total desc 
0

我JacobM同意,但有一個稍微不同的方式提出了:

SELECT 
    c.id, 
    c.name, 
    SUM(co1.invoicetotal) as PREV_MONTH, 
    SUM(co2.invoicetotal) as CUR_MONTH, 
FROM 
    customers as c, 
    customerorders as co1, 
    customerorders as co2 
WHERE 
    c.salesrep_id = 24 
    and co1.customer_id = c.id 
    and co2.customer_id = c.id 
    AND co1.orderdate BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE() 
    AND co2.orderdate > DATE_SUB(CURDATE(), INTERVAL 30 DAY) 
GROUP by c.id 
order by total desc 

不確定哪個更有效。