用SQL求和子集

时间:2017-08-27 12:48:01

标签: sql sql-server

我有两张这样的表:

| SalesId | SalesDate | SalesStore |          | StoreId |  Name   |
|---------|-----------|------------|          |---------|---------|
|    1    |  5/3/17   |     3      |          |    1    | Store A | 
|    2    |  2/2/18   |     3      |          |    2    | Store B | 
|    3    |  6/6/17   |     2      |          |    3    | Store C | 
|    4    |  7/8/17   |     3      |

我想知道是否可以仅使用SQL生成以下输出:

|  Year   | Store A | Store B | Store C |
|---------|---------|---------|---------|
|  2017   |    0    |    1    |    2    |
|  2018   |    0    |    0    |    1    |

基本上我想要每年的每家商店的销售总额。

我能够使用以下方式获得所有商店的总数:

SELECT YEAR(SalesDate) [Year], Count(1) [Sales Count]   
FROM Sales
GROUP BY YEAR(SalesDate)
ORDER BY 1

但我想知道是否可以使用单个SQL查询来执行此操作。

2 个答案:

答案 0 :(得分:1)

我通过为每年创建一个PIVOT表然后使用UNION来组合它来实现它。

SELECT '2017' AS 'Year',[Store A],[Store B],[Store C]
FROM
(
    SELECT YEAR(Sales.SalesDate) 'SalesYear',Store.[Name]
    FROM Sales
        JOIN Store ON Sales.SalesStore = StoreId
    WHERE YEAR(Sales.SalesDate) = 2017) AS table2017
PIVOT
(
    COUNT(SalesYear)
    FOR [Name] IN ([Store A],[Store B],[Store C])
) AS pivotTable2017

UNION

SELECT '2018' AS 'Year',[Store A],[Store B],[Store C]
FROM
(
    SELECT YEAR(Sales.SalesDate) 'SalesYear',Store.[Name]
    FROM Sales
        JOIN Store ON Sales.SalesStore = StoreId
    WHERE YEAR(Sales.SalesDate) = 2018)AS table2018
PIVOT
(
    COUNT(SalesYear)
    FOR [Name] IN ([Store A],[Store B],[Store C])
) AS pivotTable2018

<强>结果

+------+----------+----------+---------+
| Year | Store A  | Store B  | Store C |
+------+----------+----------+---------+
| 2017 |    0     |    1     |    2    |
| 2018 |    0     |    0     |    1    |
+------+----------+----------+---------+

答案 1 :(得分:1)

这是一个动态的交叉表解决方案,可以处理任意数量的商店......

IF OBJECT_ID('tempdb..#Store', 'U') IS NOT NULL 
DROP TABLE #Store;

CREATE TABLE #Store (
    StoreId INT NOT NULL PRIMARY KEY,
    StoreName CHAR(7) NOT NULL 
    );
INSERT #Store (StoreId, StoreName) VALUES (1, 'Store A'), (2, 'Store B'), (3, 'Store C');

IF OBJECT_ID('tempdb..#Sales', 'U') IS NOT NULL 
DROP TABLE #Sales;

CREATE TABLE #Sales (
    SalesId INT NOT NULL PRIMARY KEY,
    SalesDate DATE NOT NULL,
    SalesStore INT NOT NULL 
    );
INSERT #Sales (SalesId, SalesDate, SalesStore) VALUES 
    (1, '2017-05-03', 3), (2, '2018-02-02', 3),
    (3, '2017-06-06', 2), (4, '2017-07-08', 3);

--SELECT * FROM #Store st;
--SELECT * FROM #Sales s;

--=========================================================

DECLARE 
    @StoreCols VARCHAR(8000) = '',
    @sql VARCHAR(8000) = '',
    @DeBug BIT = 0;

SELECT 
    @StoreCols = CONCAT(@StoreCols, ',
    [', st.StoreName, '] = COUNT(CASE WHEN s.SalesStore = ', st.StoreId, ' THEN 1 END)')
FROM
    #Store st
ORDER BY
    st.StoreId;

SET @sql = CONCAT('
SELECT 
    [Year] = YEAR(s.SalesDate)', 
    @StoreCols, '
FROM
    #Sales s
GROUP BY
    YEAR(s.SalesDate);')

IF @DeBug = 1
BEGIN 
    PRINT(@sql);
END
ELSE
BEGIN
    EXEC(@sql);
END;

结果......

Year        Store A     Store B     Store C
----------- ----------- ----------- -----------
2017        0           1           2
2018        0           0           1
HTH,Jason