按多个表中的值分组的聚合 [SQL]
Aggregate grouped by values in multiple tables [SQL]
我有两个 table,#Test
和 #Control
,它们具有相同的列,看起来如下所示:
#Test: #Control:
Name Component Price Name Component Price
A a 1.00 A a 7.00
A b 2.00 A a 8.00
A a 3.00 B a 9.00
B a 4.00 B d 10.00
B a 5.00 B d 11.00
B c 6.00
但有更多的列和 Name
和 Component
的组合。
我想将它们各自聚合以获得每个 Name
和 Component
的 Price
的总和,但是我想要出现在任一列表中的所有组合的值。使用上面示例 tables 的所需输出如下所示:
#TestAgg: #ControlAgg:
Name Component SumPrice Name Component SumPrice
A a 4.00 A a 15.00
A b 2.00 A b 0.00
B a 9.00 B a 9.00
B c 6.00 B c 0.00
B d 0.00 B d 21.00
我该怎么做?
对于个人 table 以下作品:
SELECT Name
,Component
,sum(Price) as SumPrice
INTO #TestAgg
FROM #Test
GROUP BY rollup(Name,Component)
order by 1, SumPrice desc
但是我不知道如何 return 将仅存在于其他 table 中的名称组件组合归零。
你可以试试这个:
CREATE TABlE #Test(Name VARCHAR(1), Component VARCHAR(1), Price DECIMAL(14,4));
INSERT INTO #Test VALUES
('A','a',1.00)
,('A','b',2.00)
,('A','a',3.00)
,('B','a',4.00)
,('B','a',5.00)
,('B','c',6.00);
CREATE TABlE #Control(Name VARCHAR(1), Component VARCHAR(1), Price DECIMAL(14,4));
INSERT INTO #Control VALUES
('A','a',7.00)
,('A','a',8.00)
,('B','a',9.00)
,('B','d',10.00)
,('B','d',11.00);
--首先,我使用 CTE 获取 tables
的所有组合的不同列表
WITH AllCombos AS
(
SELECT DISTINCT Name,Component
FROM #Test
UNION --without "ALL" it will be distinct over the tables
SELECT DISTINCT Name,Component
FROM #Control
)
--现在我使用 LEFT JOIN
s 来获取两个结果集
-- 并使用最后的 GROUP BY
SELECT Source,Name,Component,ISNULL(SUM(Price),0) AS Price
FROM
(
SELECT 'Test' AS Source, AC.Name,AC.Component,T.Price
FROM AllCombos AS AC
LEFT JOIN #Test AS T ON AC.Component=T.Component AND AC.Name=T.Name
UNION ALL
SELECT 'Control',AC.Name,AC.Component,C.Price
FROM AllCombos AS AC
LEFT JOIN #Control AS C ON AC.Component=C.Component AND AC.Name=C.Name
) AS tbl
GROUP BY Source,Name,Component
--Clean-up
GO
DROP TABLE #Test;
DROP TABLE #Control;
结果
Control A a 15.0000
Control A b 0.0000
Control B a 9.0000
Control B c 0.0000
Control B d 21.0000
Test A a 4.0000
Test A b 2.0000
Test B a 9.0000
Test B c 6.0000
Test B d 0.0000
更新
如果确实需要两个table,可以这样写
SELECT ... INTO #ControlAgg
FROM (...) AS tbl
WHERE Source='Control'
GROUP BY ...
(与测试相同)
... 并调用两次...或者 - 在我看来更好 - 您将其写在一个公共 table 中并在查询中使用 Source
将它们分开.. .
我有两个 table,#Test
和 #Control
,它们具有相同的列,看起来如下所示:
#Test: #Control:
Name Component Price Name Component Price
A a 1.00 A a 7.00
A b 2.00 A a 8.00
A a 3.00 B a 9.00
B a 4.00 B d 10.00
B a 5.00 B d 11.00
B c 6.00
但有更多的列和 Name
和 Component
的组合。
我想将它们各自聚合以获得每个 Name
和 Component
的 Price
的总和,但是我想要出现在任一列表中的所有组合的值。使用上面示例 tables 的所需输出如下所示:
#TestAgg: #ControlAgg:
Name Component SumPrice Name Component SumPrice
A a 4.00 A a 15.00
A b 2.00 A b 0.00
B a 9.00 B a 9.00
B c 6.00 B c 0.00
B d 0.00 B d 21.00
我该怎么做?
对于个人 table 以下作品:
SELECT Name
,Component
,sum(Price) as SumPrice
INTO #TestAgg
FROM #Test
GROUP BY rollup(Name,Component)
order by 1, SumPrice desc
但是我不知道如何 return 将仅存在于其他 table 中的名称组件组合归零。
你可以试试这个:
CREATE TABlE #Test(Name VARCHAR(1), Component VARCHAR(1), Price DECIMAL(14,4));
INSERT INTO #Test VALUES
('A','a',1.00)
,('A','b',2.00)
,('A','a',3.00)
,('B','a',4.00)
,('B','a',5.00)
,('B','c',6.00);
CREATE TABlE #Control(Name VARCHAR(1), Component VARCHAR(1), Price DECIMAL(14,4));
INSERT INTO #Control VALUES
('A','a',7.00)
,('A','a',8.00)
,('B','a',9.00)
,('B','d',10.00)
,('B','d',11.00);
--首先,我使用 CTE 获取 tables
的所有组合的不同列表WITH AllCombos AS
(
SELECT DISTINCT Name,Component
FROM #Test
UNION --without "ALL" it will be distinct over the tables
SELECT DISTINCT Name,Component
FROM #Control
)
--现在我使用 LEFT JOIN
s 来获取两个结果集
-- 并使用最后的 GROUP BY
SELECT Source,Name,Component,ISNULL(SUM(Price),0) AS Price
FROM
(
SELECT 'Test' AS Source, AC.Name,AC.Component,T.Price
FROM AllCombos AS AC
LEFT JOIN #Test AS T ON AC.Component=T.Component AND AC.Name=T.Name
UNION ALL
SELECT 'Control',AC.Name,AC.Component,C.Price
FROM AllCombos AS AC
LEFT JOIN #Control AS C ON AC.Component=C.Component AND AC.Name=C.Name
) AS tbl
GROUP BY Source,Name,Component
--Clean-up
GO
DROP TABLE #Test;
DROP TABLE #Control;
结果
Control A a 15.0000
Control A b 0.0000
Control B a 9.0000
Control B c 0.0000
Control B d 21.0000
Test A a 4.0000
Test A b 2.0000
Test B a 9.0000
Test B c 6.0000
Test B d 0.0000
更新
如果确实需要两个table,可以这样写
SELECT ... INTO #ControlAgg
FROM (...) AS tbl
WHERE Source='Control'
GROUP BY ...
(与测试相同)
... 并调用两次...或者 - 在我看来更好 - 您将其写在一个公共 table 中并在查询中使用 Source
将它们分开.. .