2014-11-19 2 views
0

Рассмотрим две таблицы:Сокращение/суммирование нескольких таблиц с помощью SQL?

CREATE TABLE sales (
    saleid INT, 
    saledateid INT, 
    saleamount DECIMAL(12,2) 
); 

CREATE TABLE salelines (
    salelineid INT, 
    saleid INT, 
    quantity INT, 
    unitamount DECIMAL(12,2) 
); 

Если бы я хотел, чтобы вычислить общий объем продаж в день:

SELECT sum(quantity * unitamount) 
FROM sales 
JOIN salelines USING (saleid) 
GROUP BY saledateid; 

В большинстве случаев sales.saleamount является сумма продажи линий для этой продажи. Но в некоторых случаях корректируется saleamount, поэтому мы храним его отдельно. Таким образом, фактические общие объем продаж в день будут:

SELECT sum(saleamount) 
FROM sales 
GROUP BY saledateid; 

Однако мне нужно оба из них в том же запросе для материализованного представления, следующий не будет работать, потому что продажа может быть изготовлена ​​из более чем одной продажи линия.

SELECT sum(quantity * unitamount), sum(saleamount) 
FROM sales 
JOIN salelines USING (saleid) 
GROUP BY saledateid; 

Как это сделать? Я использую PostgreSQL, но я предпочел бы решение, совместимое с SQL.

ответ

2

Один из способов решения этой проблемы - добавить последовательный номер к линиям продаж. Затем вы можете использовать условную агрегацию выбрать только одно значение:

SELECT saledateid, sum(sl.quantity * sl.unitamount), 
     sum(case when seqnum = 1 then s.saleamount end) 
FROM sales s JOIN 
    (SELECT sl.*, row_number() over (partition by saleid order by saleid) as seqnum 
     FROM salelines sl 
    ) sl 
    USING (saleid) 
GROUP BY saledateid; 

row_number() является стандартной функцией ANSI и доступна в большинстве баз данных. Первоначально у вашего вопроса был MySQL как тег, но он там недоступен.

+0

Для краткости я не включал, что 'salelines' имеет' последовательность INT', поэтому я смог использовать 'sum (case, когда sequence = 1 then saleamount end)'. Благодаря! –

+0

@ElliotChance. , , Это будет работать и в MySQL. –