2011-04-09 24 views
0

SQL大師需要,這是殺死我的神經元。我有一個分貝結構(簡化的)是這樣的:SQL與COUNT和SUM與交叉聯合GROUP BY

DESC documents; 
    id   INT PK 
    bill_id  INT FK 
    dtype  INT -- 1=receipts, 0=invoices 
    total  DECIMAL 

DESC bills; 
    id   INT PK 
    waiter_id INT FK 

DESC waiters; 
    id   INT PK 
    name  VARCHAR 
    surname  VARCHAR 

相當不言自明的,但我需要計數和相加的總計爲所有收據(documents.dtype = 1)和發票(documents.dtype = 0),由服務員分組。 我做了兩分的SELECT:

SELECT 
     B.waiter_id, 
     WA.name, 
     WA.surname, 
     COUNT(D.id) AS Receipts, 
     SUM(D.total) AS TotReceipts 
FROM  
    documents D 
    JOIN bills B ON (B.id = D.bill_id) 
    JOIN waiters WA ON (WA.id = B.waiter_id) 
WHERE 
    D.dtype = 1   
GROUP BY 
    waiter_id; 

很好,我得到:

1, 'Mario', 'Rossi', 6, 485.20 
2, 'Luigino', 'Bianchi', 1, 456.00 

該做的第二選擇,只是改變了documents.dtype以0:

SELECT 
     B.waiter_id, 
     WA.name, 
     WA.surname, 
     COUNT(D.id) AS Invoices, 
     SUM(D.total) AS TotInvoices 
FROM  
    documents D 
    JOIN bills B ON (B.id = D.bill_id) 
    JOIN waiters WA ON (WA.id = B.waiter_id) 
WHERE 
    D.dtype = 0 
GROUP BY 
    waiter_id; 

現在我獲得:

1, 'Mario', 'Rossi', 1, 38.00 

現在我可以UNION兩個SELECTSs

SELECT 
     B.waiter_id, 
     WA.name, 
     WA.surname, 
     COUNT(D.id) AS Receipts, 
     SUM(D.total) AS TotReceipts 
FROM  
    documents D 
    JOIN bills B ON (B.id = D.bill_id) 
    JOIN waiters WA ON (WA.id = B.waiter_id) 
WHERE 
    D.dtype = 1  
GROUP BY 
    waiter_id 
UNION SELECT 
     B.waiter_id, 
     WA.name, 
     WA.surname, 
     COUNT(D.id) AS Invoices, 
     SUM(D.total) AS TotInvoices 
FROM  
    documents D 
    JOIN bills B ON (B.id = D.bill_id) 
    JOIN waiters WA ON (WA.id = B.waiter_id) 
WHERE 
    D.dtype = 0 
GROUP BY 
    waiter_id; 

我也得到:

1, 'Mario', 'Rossi', 6, 485.20 
2, 'Luigino', 'Bianchi', 1, 456.00 
1, 'Mario', 'Rossi', 1, 38.00 

嗯,正確的,但我需要通過服務員跨聯盟分組行!這就是我想要的服務員馬里奧一行:

wid wname  wsurname receipts totreceipts  invoices  totinvoices 
1, 'Mario', 'Rossi', 6,   485.20   1    38.0 
2, 'Luigino', 'Bianchi', 1,   456.00   0    0.0 

這將是好了,但我也希望兩個合計列總結行動的號碼,如:

wid wname  wsurname receipts totreceipts  invoices  totinvoices  docs totdocs 
1, 'Mario', 'Rossi', 6,   485.20   1    38.0   7  523.20 
2, 'Luigino', 'Bianchi', 1,   456.00   0    0.0    1  456.00 

那會超級超酷。

回答

2

你可以從where條款移動conditon到case聲明,如:

SELECT 
     B.waiter_id, 
     WA.name, 
     WA.surname, 
     SUM(case when d.dtype = 1 then 1 end) AS Receipts, 
     SUM(case when d.dtype = 1 then D.total end) AS TotReceipts, 
     SUM(case when d.dtype = 0 then 1 end) AS Invoices, 
     SUM(case when d.dtype = 0 then D.total end) AS TotInvoices 
FROM  
    documents D 
    JOIN bills B ON (B.id = D.bill_id) 
    JOIN waiters WA ON (WA.id = B.waiter_id) 
GROUP BY 
    waiter_id 
+0

嘿這個窩rks喜歡魅力,非常感謝的人! – vulkanino 2011-04-09 11:59:08

+0

總計(Receipts + Invoices)和(TotReceipts + TotInvoices)呢?我應該重寫像SUM這樣的選擇(當d.dtype = 1然後1結束時)+ SUM(當d.dtype = 0,然後1結束時)AS TotalDocs ?? – vulkanino 2011-04-09 12:01:11

+1

@vulkanino:是的,或者只是總和(在(0,1)然後是1結束時d.dtype的情況)TotalDocs' – Andomar 2011-04-09 12:21:09

0

該查詢返回你問

SELECT 
    B.waiter_id, 
    WA.name, 
    WA.surname, 
    (select count(id)    from documents where dtype = 0 and bill_id = B.id) AS Invoices, 
    (select isnull(sum(total), 0) from documents where dtype = 0 and bill_id = B.id) AS TotInvoices, 
    (select count(id)    from documents where dtype = 1 and bill_id = B.id) AS Receipts, 
    (select isnull(sum(total), 0) from documents where dtype = 1 and bill_id = B.id) AS TotReceipts 
    FROM bills B 
inner join waiters WA on WA.id = B.waiter_id 

總結所有的總計,可以使內部選擇以總計爲:

select data.*, 
     data.Invoices + data.Receipts as docs, 
     data.TotInvoices + data.TotReceipts as totaldocs 
    from (
    select 
    B.waiter_id, 
    WA.name, 
    WA.surname, 
    (select count(id)    from documents where dtype = 0 and bill_id = B.id) AS Invoices, 
    (select isnull(sum(total), 0) from documents where dtype = 0 and bill_id = B.id) AS TotInvoices, 
    (select count(id)    from documents where dtype = 1 and bill_id = B.id) AS Receipts, 
    (select isnull(sum(total), 0) from documents where dtype = 1 and bill_id = B.id) AS TotReceipts 
    from bills B 
inner join waiters WA on WA.id = B.waiter_id 
) data 
+1

我不得不承認Andomar的解決方案更加優化。我的解決方案可能會導致性能問題 – 2011-04-09 12:42:24

+0

是的,他的解決方案更優雅,但無論如何感謝。我永遠不會完全理解CASE指令:) – vulkanino 2011-04-09 13:06:09