2015-06-25 2 views
2

Я хочу работать продаж по видам продукции, сгруппированных по дате выпуска, но и сгруппированы по возрасту этого продукта, когда продается, что-то вроде этого:SQL разработать продаж на продукт, принимая во внимание возраст

 | 3 months | 6 months  
2015-01 | 28.1  | 37.1 
2015-02 | 29.3  | 35.6 

Таким образом, 28,1 - это среднее количество проданных продуктов каждого типа, через 3 месяца после выпуска, для продуктов, выпущенных в 2015-01 годах. Есть, очевидно, больше продуктов, проданных через 6 месяцев после даты выпуска, 37.1.

Следующая SQL получает список продаж:

SELECT 
    d.item    AS title, 
    d.quantity, 
    a.firstdate   AS release_date, 
    i.date    AS invoice_date, 
    i.date - a.firstdate AS age 

FROM invoices i 
    JOIN invoice_details d ON i.id = d.invoice_id 

    JOIN (SELECT 
      d.item, 
      d.binding, 
      min(i.date) AS firstdate 
     FROM invoices i 
      JOIN invoice_details d ON i.id = d.invoice_id 
     GROUP BY d.item, d.binding) AS a ON a.item = d.item AND a.binding = d.binding 

WHERE 
    i.discount != 100 AND d.price > 0 
    AND (d.binding != 'Hardback' OR d.binding != 'Ebooks') 

ORDER BY title, invoice_date 

И результат выглядит примерно так:

title | quantity | release date | invoice date | age 
A  | 1  | 2013-11-14 | 2013-11-14 | 0 
A  | 2  | 2013-11-14 | 2013-12-14 | 30 
A  | 3  | 2013-11-14 | 2014-01-14 | 60 
A  | 4  | 2013-11-14 | 2014-02-14 | 90 
A  | 5  | 2013-11-14 | 2014-03-14 | 120 
B  | 6  | 2013-11-14 | 2013-11-14 | 0 
B  | 7  | 2013-11-14 | 2013-12-14 | 30 
B  | 8  | 2013-11-14 | 2014-01-14 | 60 
B  | 9  | 2013-11-14 | 2014-02-14 | 90 
B  | 10  | 2013-11-14 | 2014-03-14 | 120 

Для продукта А, общий объем продаж 3 месяца после даты выпуска 2013- 11-14 равны 1 + 2 + 3 = 6. Для продукта B общий объем продаж через 3 месяца составляет 6 + 7 + 8 = 21. Средние продажи за год на 2013-11 год, 3 месяца после этого (6 + 21) /2 = 13,5

В течение 6 месяцев после его ((1 + 2 + 3 + 4 + 5) + (6 + 7 + 8 + 9 + 10))/2 = 27,5

Дата выпуска - это только первое время, когда продукт был продан - это то, к чему относится объединенный подзапрос. Вероятно, это лучший способ сделать это.

Я попробовал это, чтобы получить средние по 3, 6, 12 и 24 месяцев:

SELECT 
    to_char(a.release_date, 'YYYY-MM') AS release_date, 

    avg(CASE WHEN i.date - a.release_date < 92 
    THEN d.quantity END)    AS three_months, 

    avg(CASE WHEN i.date - a.release_date < 183 
    THEN d.quantity END)    AS six_months, 

    avg(CASE WHEN i.date - a.release_date < 365 
    THEN d.quantity END)    AS twelve_months, 

    avg(CASE WHEN i.date - a.release_date < 730 
    THEN d.quantity END)    AS twentyfour_months 

FROM invoices i 
    JOIN invoice_details d ON i.id = d.invoice_id 

    JOIN (SELECT 
      d.item, 
      d.binding, 
      min(i.date) AS release_date 
     FROM invoices i 
      JOIN invoice_details d ON i.id = d.invoice_id 
     GROUP BY d.item, d.binding) AS a ON a.item = d.item AND a.binding = d.binding 

WHERE 
    i.discount != 100 AND d.price != 0 
    AND (d.binding != 'Hardback' OR d.binding != 'Ebooks') 


GROUP BY release_date 
ORDER BY release_date desc 

Очевидно, что это совершенно неправильно, потому что это не группировка результатов по названию. Это дает мне средние предметы за заказ, а не средние предметы за титул.

Кстати, я застрял на Postgres 8.2.

+0

Измените свой вопрос и добавьте образцы данных. –

+0

Я добавил примеры данных для первого запроса, какие образцы данных вы имели в виду? – eggbert

ответ

0

Если я вас правильно понял, это то, что вы хотите:

SELECT 
    to_char(date, 'YYYY-MM') AS release_date, 
    avg(CASE WHEN age < 92 THEN quantity ELSE 0 END) AS three_months, 
    avg(CASE WHEN age < 183 THEN quantity ELSE 0 END) AS six_months, 
    avg(CASE WHEN age < 365 THEN quantity ELSE 0 END) AS twelve_months, 
    avg(CASE WHEN age < 730 THEN quantity ELSE 0 END) AS twentyfour_months 
FROM (
    SELECT d.item, d.quantity, (i.date - first_release.date) AS age, fr.date 
    FROM invoice_details d 
    JOIN (
    SELECT d.item, min(i.date) AS date 
    FROM invoice_details d 
    JOIN invoices i ON i.id = d.invoice_id 
    WHERE d.binding != 'Hardback' AND d.binding != 'Ebooks' 
    GROUP BY d.item) AS fr USING (item) 
    JOIN invoice i ON i.id = d.invoice_id 
    WHERE i.discount != 100 AND d.price > 0) AS foo 
GROUP BY release_date 
ORDER BY release_date; 

Это вполне очевидно, непроверенное, потому что я даже не могу вспомнить, когда я в последний раз коснулся 8.2 установки. Ваша версия не имеет общих табличных выражений или боковых соединений, чтобы назвать две критические функции в более поздних версиях, которые сделали бы это более интуитивным.

В любом случае, нужно сначала рассчитать возраст каждого счета-фактуры относительно даты выпуска книги для каждой проданной книги, а затем усреднить ее в течение различных периодов времени. Посмотрите внимательно на фильтры, когда я переместил их и немного изменил их ((d.binding != 'Hardback' OR d.binding != 'Ebooks'), скорее всего, не то, что вы хотите).

+0

Он работает с небольшими исправлениями, но не дает правильных результатов. Он производит номера в основном в диапазоне 0-1, тогда как я знаю, что они больше похожи на 30-70. По-прежнему кажется, что они обрабатывают титулы отдельно, так что средние значения - это позиции за заказ, а не элементы за заголовок. – eggbert

Смежные вопросы