2016-06-08 2 views
1

У меня есть следующие таблицы продаж:SQL запрос для получения текущих и последний год продажи

Date  Store Sales 
1/1/2015 St01 12123 
1/1/2015 St02 3123 
1/1/2016 St01 4213 
1/1/2016 St03 2134 

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

Date  Store This year Sales Last Year Sales 
1/1/2016 St01 4213    1212 
1/1/2016 St02 0     3123 
1/1/2016 St03 2134    0 

Мой запрос следующим образом:

SELECT CY.DATE, 
     CY.store cy.Sales, 
     LY.sales 
FROM sales CY, 
     sales LY 
WHERE CY.store(+) = LY.store(+) 
     AND LY.DATE = CY.DATE - 365 
+0

Вам даже нужна эта первая колонка «Дата» там в результатах yoru? – chungtinhlakho

+0

Да, мне это понадобится для еженедельных и ежемесячных продаж. – badry

ответ

0

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

WITH AllYear AS 
(select to_date('2016-01-01', 'yyyy-mm-dd') + level - 1 AS dobs 
    from dual 
    connect by level <= 366) 

SELECT dobs AS "DATE", 
     Store, 
     nvl(SUM(CASE 
       WHEN t.Date = dobs THEN 
        t.sales 
       END), 
      0) AS "This Year Sales", 
     nvl(SUM(CASE 
       WHEN t.Date = dobs-365 THEN 
        t.sales 
       END), 
      0) AS "Last Year Sales" 
    FROM Sales t,AllYear 
where dobs='01-Jan-2016' 
GROUP BY Store 
ORDER BY Store; 
-2

Я работаю только с SQL Server. Если что-то другое, попробуйте применить ту же логику.

Декларирование временную таблицу для проверки запроса:

DECLARE @Sales TABLE (
    [Date] DATE, 
    Store NVARCHAR(10), 
    Sales INT 
) 

INSERT INTO @Sales VALUES 
    ('1/1/2015','St01',12123), 
    ('1/1/2015','St02',3123), 
    ('1/1/2016','St01',4213), 
    ('1/1/2016','St03',2134); 

SELECT * FROM @Sales; 

Фактический запрос:

SELECT 
    CY_Date = CASE 
     WHEN CY.Date IS NULL THEN DATEADD(YEAR, 1, LY.Date) 
     ELSE CY.Date 
     END, 
    LY_Date = CASE 
     WHEN LY.Date IS NULL THEN DATEADD(YEAR, -1, CY.Date) 
     ELSE LY.Date 
     END, 
    Store = CASE 
     WHEN CY.Store IS NULL THEN LY.Store 
     ELSE CY.Store 
     END, 
    ISNULL(CY.Sales, 0) AS CY_Sales, 
    ISNULL(LY.Sales, 0) AS LY_Sales 
FROM @Sales CY 
FULL JOIN @Sales LY ON (CY.Store = LY.Store AND LY.Date = DATEADD(YEAR, -1, CY.Date)) 
WHERE (CY.Date = '1/1/2016' OR CY.Date IS NULL) 
    AND (LY.Date = DATEADD(YEAR, -1, '1/1/2016') OR LY.Date IS NULL); 

Результат:

CY_Date  LY_Date  Store CY_Sales LY_Sales 
2016-01-01 2015-01-01 St01 4213  12123 
2016-01-01 2015-01-01 St03 2134  0 
2016-01-01 2015-01-01 St02 0   3123 

Как это работает:

  • ПОЛНЫЙ РЕГИСТРИРУЙТЕСЬ будет совместит в магазин и строки из текущего и предыдущего года.
  • Предложение WHERE будет фильтроваться к текущей дате '1/1/2016'. NULL разрешены, потому что иногда у вас нет линий для текущего или за последний год.
  • В столбцах CASES используются для создания дат, если они являются нулевыми (если текущая дата равна нулю, получите последний год + 1 год и наоборот), чтобы создать хранилище, если они являются нулевыми и помещаются вместо нуля в столбцах продаж.
+1

Ваш ответ для SQLServer не оракула. В oracle нет функции dateadd. –

+0

Вы прочитали первое предложение моего ответа? – Edu

+0

Используйте 'add_months (CY.Date, 12)' вместо DATEADD. – Edu

0

То, что вам нужно, называется поворотным столом. Хотя Oracle имеет специальные пункты, чтобы сделать это, вы можете использовать только простой и чистый SQL, чтобы сделать так, как это:

SELECT store, 
     SUM(CASE WHEN Extract(year FROM DATE) = Extract(year FROM SYSDATE) THEN 
      sales 
      ELSE 0 
      END) AS "This year Sales", 
     SUM(CASE WHEN Extract(year FROM DATE) = Extract(year FROM SYSDATE) - 1 THEN 
      sales 
      ELSE 0 
      END) AS "Last year Sales" 
FROM sales 
WHERE Extract(year FROM DATE) >= Extract(year FROM SYSDATE) - 1 
GROUP BY store 
ORDER BY store 

Было бы показать:

Store This year Sales Last year Sales 
St01  4213    12123 
St02  0     3123 
St03  2134    0 

Обратите внимание, что не имеет смысла иметь в столбец date как первый колонка. Вы не можете группировать его, чтобы показать нужный результат.

См эквивалент этого запроса здесь на скрипку: http://sqlfiddle.com/#!15/7662d8/6

+0

Downvoter заботится, чтобы объяснить? –

+0

Спасибо за очень хороший ответ, так что это будет суммировать весь год продаж, но что, если я хочу делать это каждую неделю и месяц за месяцем? – badry

+0

Тогда вам придется сломать даты в эти периоды. «Экстракт» может сделать это легко по месяцам. В течение недели это было бы немного сложнее с момента его извлечения, вам нужно было бы использовать комбинацию типа 'to_number (to_char (to_date ('01/01/2016 ',' MM/DD/YYYY '), WW ')) 'this возвращает номер недели, тогда вы можете группировать его, но вам нужно будет иметь периоды, прямо сейчас у вас есть только даты. Вы должны задать новый вопрос. Это совсем другое. Пожалуйста, выберите ответ, который лучше подходит вашему вопросу и отметьте его как принятый. Это поможет другим. –

0

Oracle Setup:

CREATE TABLE sales ("DATE", Store, Sales) AS 
SELECT DATE '2015-01-01', 'St01', 12123 FROM DUAL UNION ALL 
SELECT DATE '2015-01-01', 'St02', 3123 FROM DUAL UNION ALL 
SELECT DATE '2016-01-01', 'St01', 4213 FROM DUAL UNION ALL 
SELECT DATE '2016-01-01', 'St03', 2134 FROM DUAL; 

Запрос:

SELECT TRUNC(SYSDATE, 'YY') AS "DATE", 
     Store, 
     SUM(CASE WHEN "DATE" = TRUNC(SYSDATE, 'YY') 
       THEN sales END) 
     AS "This year sales", 
     SUM(CASE WHEN "DATE" = ADD_MONTHS(TRUNC(SYSDATE, 'YY'), -12) 
       THEN sales END) 
     AS "Last year sales" 
FROM sales 
GROUP BY store 
ORDER BY store; 

Выходной:

DATE    STORE This year sales Last year sales 
------------------- ----- --------------- --------------- 
2016-01-01 00:00:00 St01    4213   12123 
2016-01-01 00:00:00 St02        3123 
2016-01-01 00:00:00 St03    2134     
-1

Общее решение является полного внешнего соединения, который включает в себя все записи, как из объединения таблиц. Я не знаю синтаксис Oracle, но в MS SQL Server это будет что-то вроде этого:

SELECT ISNULL(CY.DATE, LY.DATE) as DATE, 
     ISNULL(CY.store, LY.store) as STORE, 
     isnull(cy.Sales, 0), 
     isnull(LY.sales, 0) 
FROM sales CY FULL OUTER JOIN sales LY 
    ON CY.store = LY.store 
     AND (CY.DATE IS NULL OR 
      DATEPART(year, LY.DATE) = DATEPART(year, CY.DATE) - 1 

ISNULL(a, b) дает a если A IS NOT NULL, иначе b. DATEPART выдает указанную часть даты; Я сравниваю разницу ровно на один год, а не на 365 дней, если «прошлый год» - високосный год/

+1

Это не MS SQL, и это также не FULL, JOIN или что-то связанное. Это поворотный вопрос. –

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