SQL查询获取当前和去年的销售额

时间:2016-06-08 22:41:38

标签: sql oracle

我有下表Sales:

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 

5 个答案:

答案 0 :(得分:0)

您需要什么称为透视表。虽然Oracle有特定的条款来执行此操作,但您可以使用纯SQL和纯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

答案 1 :(得分:0)

Oracle安装程序

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                 

答案 2 :(得分: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;

答案 3 :(得分:-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,否则为bDATEPART提取日期的指定部分;我正在比较一年而不是365天的差异,以防“去年”是闰年/

答案 4 :(得分:-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

工作原理:

  • FULL JOIN将结合商店和当前和前一年的行。
  • WHERE子句将按当前日期“1/1/2016”进行过滤。允许使用NULL,因为有时您没有当前或去年的行。
  • 在列上,CASES用于创建日期(如果它们为空(如果当前日期为空,获取去年+ 1年,反之亦然),则创建商店,如果它们为空并放置销售栏上的零而非零。