2016-05-25 4 views
0

У меня есть таблица, которая включает в себя следующие поля:Insert «Фиктивные Ряды» В SQL с агрегатными функциями

Компания фрукты Дата шт цена TOTAL_PRICE

У меня есть запрос, который суммирует данные :

SELECT 
company, 
extract(year from date) as year, 
case 
    when EXTRACT(MONTH FROM DATE) <= 3 
     THEN 'Q1' 
    WHEN EXTRACT(MONTH FROM DATE) BETWEEN 4 AND 6 
     THEN 'Q2' 
    WHEN EXTRACT(MONTH FROM DATE) BETWEEN 7 AND 9 
     THEN 'Q3' 
    WHEN EXTRACT(MONTH FROM DATE) BETWEEN 10 AND 12 
     THEN 'Q4' 
    ELSE 'UNKNOWN' 
END AS QUARTER, 
COUNT(*) AS purchases, 
SUM(QTY) AS total_fruit_purchased, 
SUM(total_price) AS COMISSION 
FROM fees.fruit_paid 
where extract(year from date) >= 2015 
      GROUP BY 
       company, 
       extract(year from date), 
       case 
        when EXTRACT(MONTH FROM DATE) <= 3 
         THEN 'Q1' 
        WHEN EXTRACT(MONTH FROM DATE) BETWEEN 4 AND 6 
         THEN 'Q2' 
        WHEN EXTRACT(MONTH FROM DATE) BETWEEN 7 AND 9 
         THEN 'Q3' 
        WHEN EXTRACT(MONTH FROM DATE) BETWEEN 10 AND 12 
         THEN 'Q4' 
        ELSE 'UNKNOWN' 
       END 
        ORDER BY 
         company, 
         YEAR, 
         QUARTER 

Как я могу включить фиктивные строки в вывод, если нет данных для определенной компании за год & квартал в моем временном интервале?

ответ

0

Это немного сложно, поэтому позвольте мне провести вас через него. Во-первых, вам нужен список компаний, в том числе компаний, у которых нет покупок. Вы можете получить, что с:

SELECT DISTINCT company 
FROM fruit_paid; 

И вы могли бы просто использовать, чтобы получить краткую информацию для всех компаний, и все время что-то вроде этого:

WITH 
    company_names as 
    (SELECT DISTINCT company 
    FROM fruit_paid) 

SELECT company_names.company, sum(fruit_paid.qty) as total_fruit_purchased 
FROM company_names 
    LEFT OUTER JOIN fruit_paid 
    ON company_names.company = fruit_paid.company 
GROUP BY company_names.company; 

Две вещи происходит там: 1- Я беру предыдущий запрос («SELECT DISTINCT ...») и делаю его чем-то, называемым общим табличным выражением - это просто означает, что я могу использовать этот запрос, например таблицу. 2- Я использую LEFT OUTER JOIN, который будет использовать левую таблицу, чтобы определить строки, и присоединиться ко всему из правой таблицы, где это возможно.

Это основа того, что необходимо для этого. Вы можете получить список лет с функцией generate_series. Что-то вроде:

SELECT extract(YEAR from generate_series) as year 
FROM generate_series('2015-01-01'::date, 
        '2016-01-01'::date, 
        '1 year'); 

Что вы можете развернуться и добавить к предыдущему запросу:

WITH 
    company_names as 
    (SELECT DISTINCT company 
    FROM fruit_paid), 
    years as 
    (SELECT extract(YEAR from generate_series) as year 
    FROM generate_series('2015-01-01'::date, 
          '2016-01-01'::date, 
          '1 year')) 

SELECT company_names.company, 
     years.year, 
     sum(fruit_paid.qty) as total_fruit_purchased 
FROM company_names 
    CROSS JOIN years 
    LEFT OUTER JOIN fruit_paid 
    ON company_names.company = fruit_paid.company 
    AND extract(YEAR from fruit_paid.date) = years.year 
GROUP BY company_names.company, years.year; 

Использование CROSS JOIN там получает вас один ряд в сочетании с левой таблицы (company_names) и правую таблицу (years). Другими словами, один ряд для каждой компании и года, независимо от покупок. Чтобы вы получили данные о покупке, вы снова присоединились к fruit_paid.

Последний кусок квартала. Там простой способ, чтобы получить список всех кварталов:

VALUES ('Q1'), ('Q2'), ('Q3'), ('Q4'); 

Так давайте добавим, что в:

WITH 
    company_names as 
    (SELECT DISTINCT company 
    FROM fruit_paid), 
    years as 
    (SELECT extract(YEAR from generate_series) as year 
    FROM generate_series('2015-01-01'::date, 
          '2016-01-01'::date, 
          '1 year')), 
    quarters (quarter) as 
    (VALUES ('Q1'), ('Q2'), ('Q3'), ('Q4')) 

SELECT company_names.company, 
     years.year, 
     quarters.quarter, 
     sum(fruit_paid.qty) as total_fruit_purchased 
FROM company_names 
    CROSS JOIN years 
    CROSS JOIN quarters 
    LEFT OUTER JOIN fruit_paid 
    ON company_names.company = fruit_paid.company 
    AND extract(YEAR from fruit_paid.date) = years.year 
    AND quarters.quarter = case 
          WHEN extract(MONTH FROM date) <= 3 
           THEN 'Q1' 
          WHEN extract(MONTH FROM date) BETWEEN 4 AND 6 
           THEN 'Q2' 
          WHEN extract(MONTH FROM date) BETWEEN 7 AND 9 
           THEN 'Q3' 
          WHEN extract(MONTH FROM date) BETWEEN 10 AND 12 
           THEN 'Q4' 
          ELSE 'UNKNOWN' 
          END 
GROUP BY company_names.company, years.year, quarters.quarter; 

только новые модные вещи мы сделали здесь было дать немного больше определение для quarters общего table - мы добавили имя столбца. Для псевдо-запросов, таких как VALUES, может быть удобно определить имена для возвращаемых столбцов, и это делает запрос более понятным позже (иначе мы будем присоединяться к quarters.column, что просто сложно понять) ,

Надеюсь, что это поможет.

Вот некоторые из соответствующей документации:

  • Table Expressions, переходящий с использованием результатов запроса в виде таблиц, а также затрагивает различные типы объединений.
  • WITH queries, в котором конкретно говорится об общих табличных выражениях.
  • VALUES, который я включаю для полноты.
  • Set-Returning Functions, который описывает все способы использования generate_series.
Смежные вопросы