2015-07-23 3 views
2

Получите список всех заказов клиентов по месяцам, и если у клиента нет заказа в данном месяце, укажите строку для этого месяца с 0 в качестве общей суммы заказа. В одном заявлении? Итоги уже рассчитаны, нет необходимости в агрегатной функции.Заказ клиента в целом по месяцам, со всеми перечисленными клиентами, даже если у клиента не было заказов в месяц, в одном заявлении SQL?

Использование функции коалесценции приемлемо.

Учитывая перечень сумм заказов клиентов в месяц:

create table orders (cust char(1), month num, exps num); 
insert into orders 
    values('a', 1, 5) 
    values('b', 2, 4) 
    values('c', 1, 8); 

и список клиентов:

create table custs(cust char(1)); 
insert into custs 
    values('a') 
    values('b') 
    values('c') 
    values('d'); 

Сформировать эту таблицу:

cust, month, exps 
a, 1, 5 
a, 2, 0 
b, 1, 0 
b, 2, 4 
c, 1, 8 
c, 2, 0 
d, 1, 0 
d, 2, 0 
+0

базы данных вы используете? –

+0

Какая СУБД вы используете? Это можно легко сделать с помощью 'generate_series()' в Postgres. С рекурсивным общим табличным выражением в ANSI SQL. –

+0

@vkp Это будет сервер SAS. – Snorex

ответ

1
select or1.cust, a.[month], sum(coalesce(or2.[exps], 0)) as exps 
from (
    select 1 as[month] union all select 2 
) a cross join (select distinct cust from custs) or1 
left join orders or2 on or2.[month] = a.[month] and or2.cust = or1.cust 
group by or1.cust, a.[month] 
order by or1.cust,a.[month] 

Sqlfiddle

И еще одна версия с собирание всех существующих месяцев со стола. Результаты же для наших тестовых данных:

select or1.cust, a.[month], sum(coalesce(or2.[exps], 0)) as exps 
from (
    select distinct [month] from orders 
) a cross join (select distinct cust from custs) or1 
left join orders or2 on or2.[month] = a.[month] and or2.cust = or1.cust 
group by or1.cust, a.[month] 
order by or1.cust,a.[month] 

Sqlfiddle

+0

Исправлено. Я изменил крест применительно к перекрестному соединению. Не могли бы вы его использовать? –

+0

Выбор ответа, потому что CROSS JOIN более читабельна, я думаю, а также использование sqlfiddle в демонстрации ответа. – Snorex

0

Изготовление декартово произведение клиентов и месяцы были первой трещиной в яйце ... а затем левое соединение/слияние с результатом.

select all_possible_months.cust, 
     all_possible_months.month, 
     coalesce(orders.exps,0) as exps 
from 
     (select order_months.month, 
      custs.cust 
     from 
      (select distinct month 
      from 
      orders 
      ) as order_months, 
      custs 
     ) all_possible_months 
left join 
     orders on(
      all_possible_months.cust = orders.cust and 
      all_possible_months.month = orders.month 
      );