/ / Sumando subconjuntos con SQL - sql, sql-server

Sumando subconjuntos con SQL - sql, sql-server

Tengo dos mesas como esta:

| 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      |

Me gustaría saber si es posible generar la siguiente salida usando solo SQL:

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

Básicamente quiero la suma de ventas de cada tienda por año.

Pude obtener el total de todas las tiendas usando:

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

Pero me gustaría saber si es posible hacerlo utilizando una sola consulta SQL.

Respuestas

1 para la respuesta № 1

Aquí hay una solución dinámica de tablas cruzadas que manejará cualquier número de tiendas ...

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;

Los resultados...

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

HTH, Jason


1 para la respuesta № 2

Lo hice trabajar creando un PIVOT tabla para cada año y luego utilizando una UNION para combinarlos.

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

RESULTADOS

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