用SQL对子集求和

用SQL对子集求和,sql,sql-server,Sql,Sql Server,我有两张这样的桌子: | SalesId | SalesDate | SalesStore | | StoreId | Name | |---------|-----------|------------| |---------|---------| | 1 | 5/3/17 | 3 | | 1 | Store A | | 2 | 2/2/18 | 3

我有两张这样的桌子:

| 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查询来实现这一点

我通过为每年创建一个
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    |
+------+----------+----------+---------+

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

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

嗯,Jason可能必须阅读PIVOT查询如果SalesStore的数量不固定,您需要PIVOT或dynamic PIVOT。这里可以找到很多答案。如果是固定数量的存储,则可以使用条件聚合。如果不是的话,就像人们在我之前所说的,PIVOT是一个不错的选择。谢谢大家,我会搜索PIVOT表的。。。