2011-04-09 3 views
0

SQL 전문가가 필요합니다. 이것은 내 뉴런을 죽이는 것입니다.교차 UNION GROUP이있는 COUNT 및 SUM이있는 SQL

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 : I 이런 DB 구조 (단순)가 = 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 

그냥 0으로 documents.dtype을 변경, 두 번째 SELECT했던 지금

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; 

및 I 얻을 수 :

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

1, 'Mario', 'Rossi', 6, 485.20 
2, 'Luigino', 'Bianchi', 1, 456.00 
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; 

내가 얻을 수 있습니다! 그건 내가 웨이터 마리오에 대한 한 줄을 원하는 것입니다 :

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 

: 그냥 좋은 것, 그러나 나는 또한 합계 업하는 숫자를 같이 두 개 더 총 열을 싶습니다

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 

그리고 그것은 초 - 초 - 멋지다.

당신처럼 case 문에 where 절에서 실행 조건을 움직일 수

답변

2

:

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

+0

합계 (영수증 + 인보이스) 및 (TotReceipts + TotInvoices)는 어떻게됩니까? SUM (d.dtype = 1 then 1 end) + SUM (d.dtype = 0, 1 end의 경우) AS TotalDocs와 같은 select에서 모든 것을 다시 써야합니까 ?? – vulkanino

+1

@vulkanino : 맞습니다. 또는 합계 (dd 유형이 (0,1)에서 1 끝나는 경우) TotalDocs' – Andomar

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의 솔루션이 더 최적화되었음을 인정해야합니다. 내 솔루션 성능 문제가 발생할 수 있습니다. –

+0

예, 그의 솔루션은 더 우아하지만 어쨌든 고마워요. 나는 완전히 CASE 명령을 이해할 수 없을 것이다 :) – vulkanino