UNION ALL 的替代方法以获取聚合数据
Alternatives to UNION ALL to get aggregate data
联合许多 table 以查看来自许多源系统的聚合数据,有哪些替代 UNION ALL 的方法?我正在寻找超越 T-SQL.
的解决方案
假设我们有 3 个源 table,我们想通过 id:
加入它们
表A
id Adata
1 8383
2 2707
3 6181
4 6708
表B
id Bdata
1 2669
1 8582
2 6335
2 7355
3 7355
3 2277
4 2789
4 8566
表C
id Adata
1 2856
2 1364
3 4476
4 3311
4 8073
想要的结果table我想得到:
我现在获取它的原始方式(通过 UNION ALL):
通过创建由许多 table 组成的巨大 table 和许多空值来达到预期的结果,如果我们有许多列和许多 table秒。如果我们想加入不同的信息系统,如会计、工资单、采购等,我认为这是一个常见问题。
最终目标是为 Excel 用户提供聚合数据,并有机会向下钻取仅限于选定的 table。例如,通过双击第一个 Bdata 11251 中的所需结果 table,用户有兴趣只查看构成该数字的数据。但是用户却得到了这个:
更新。我想保留深入研究数据的机会。因此,如果我双击 Excel 中的结果 table,我希望能够看到每个 ID 的所有详细信息。
对于你的例子,一个简单的连接似乎就足够了,你为什么需要UNION ALL
?
SELECT A.id,
SUM(A.Adata),
SUM(B.Bdata),
SUM(C.Cdata)
FROM TableA A
JOIN TableB B ON A.id = B.id
JOIN TableC C ON A.id = C.id
GROUP BY A.id
如果要显示总计,可以使用WITH ROLLUP
:
SELECT ISNULL(sub.id,'Total') AS "id",
sub.Adata,
sub.Bdata,
sub.Cdata
FROM (
SELECT A.id,
SUM(A.Adata) AS Adata,
SUM(B.Bdata) AS Bdata,
SUM(C.Cdata) AS Cdata
FROM TableA A
JOIN TableB B ON A.id = B.id
JOIN TableC C ON A.id = C.id
GROUP BY A.id WITH ROLLUP) sub
您应该使用内部联接。 Union (All) 似乎没有必要,除非某些表中缺少某些 ID:
Select coalesce(cast(i.id as varchar(10)), 'SUM')
, isnull(sum(A.data), '')
, isnull(sum(B.data), '')
, isnull(sum(C.data), '')
From (Select id From A
Union Select id From B
Union Select id From C
) as i
left Join A on A.id = i.id
left Join B on B.id = i.id
left Join C on C.id = i.id
group by grouping sets (i.id, ())
分组集添加总行
这可以解决您的问题。
select id,Adata,Bdata,SUM(Cdata) as Cdata
from ((select id,Adata,SUM(Bdata) as Bdata
from (A join B using(id)) group by id)T join C using(id))
group by id
这可能不是一个合适的答案。
你在混淆概念。 UNION ALL 是很少需要和使用的东西。将相似的结果集粘合在一起时会用到它。这里不是这种情况。
为了连接 tables,您当然应该使用连接。您使用 GROUP BY(您的案例中的 ID)声明的每个组都会得到一个结果行。您使用 SUM、MAX、COUNT 等聚合函数来聚合数据。
要编写的查询取决于是否所有 ID 都出现在 table A 和其他 table 中。区别主要是当时使用的连接类型。
ID 必须出现在所有 table 中:
select id, sum(a.adata), sum(b.bdata), sum(c.cdata)
from a
join b using (id)
join c using (id)
group by id;
ID 必须在 table 中唯一:
select id, sum(a.adata), coalesce(sum(b.bdata),0), coalesce(sum(c.cdata),0)
from a
left join b using (id)
left join c using (id)
group by id;
ID 不必存在于任何特定的 table:
select id, coalesce(sum(a.adata),0), coalesce(sum(b.bdata),0), coalesce(sum(c.cdata),0)
from a
full outer join b using (id)
full outer join c using (id)
group by id;
编辑:我应该补充一点 SQL 服务器不支持 USING 子句(这是标准的 SQL2003)。您可以将其替换为 ON 子句,只要您不需要完全外部联接就很容易,如果没有 using 子句则要复杂得多。
并且:通过使用 group by rollup(id)
而不是仅使用 group by id
,您会在最后得到一个总和行。
获得所需的输出(使用 SUM 行)
SELECT CAST(A.id AS VARCHAR(100)) AS ID,
(SELECT SUM(Aa.Adata) FROM TableA Aa WHERE A.id = Aa.id GROUP BY Aa.id) AS Adata,
(SELECT SUM(Ba.Bdata) FROM TableB Ba WHERE B.id = Ba.id GROUP BY Ba.id) AS Bdata,
(SELECT SUM(Ca.Cdata) FROM TableC Ca WHERE C.id = Ca.id GROUP BY Ca.id) AS Cdata
FROM TableA A
INNER JOIN TableB B ON A.id = B.id
INNER JOIN TableC C ON A.id = C.id
GROUP BY A.id, B.id, C.id
UNION ALL
SELECT CAST('SUM' AS VARCHAR(100)),
SUM(A.Adata), (SELECT
SUM(B.Bdata)
FROM TableB B), (SELECT
SUM(C.Cdata)
FROM TableC C)
FROM TableA A
输出:
ID Adata Bdata Cdata
1 8383 11251 2856
2 2707 6335 1364
3 6181 9632 4476
4 6708 11355 11384
SUM 23979 38573 20080
SQL Fiddle: http://sqlfiddle.com/#!3/ba58d/11/0
联合许多 table 以查看来自许多源系统的聚合数据,有哪些替代 UNION ALL 的方法?我正在寻找超越 T-SQL.
的解决方案假设我们有 3 个源 table,我们想通过 id:
加入它们表A
id Adata
1 8383
2 2707
3 6181
4 6708
表B
id Bdata
1 2669
1 8582
2 6335
2 7355
3 7355
3 2277
4 2789
4 8566
表C
id Adata
1 2856
2 1364
3 4476
4 3311
4 8073
想要的结果table我想得到:
我现在获取它的原始方式(通过 UNION ALL):
通过创建由许多 table 组成的巨大 table 和许多空值来达到预期的结果,如果我们有许多列和许多 table秒。如果我们想加入不同的信息系统,如会计、工资单、采购等,我认为这是一个常见问题。
最终目标是为 Excel 用户提供聚合数据,并有机会向下钻取仅限于选定的 table。例如,通过双击第一个 Bdata 11251 中的所需结果 table,用户有兴趣只查看构成该数字的数据。但是用户却得到了这个:
更新。我想保留深入研究数据的机会。因此,如果我双击 Excel 中的结果 table,我希望能够看到每个 ID 的所有详细信息。
对于你的例子,一个简单的连接似乎就足够了,你为什么需要UNION ALL
?
SELECT A.id,
SUM(A.Adata),
SUM(B.Bdata),
SUM(C.Cdata)
FROM TableA A
JOIN TableB B ON A.id = B.id
JOIN TableC C ON A.id = C.id
GROUP BY A.id
如果要显示总计,可以使用WITH ROLLUP
:
SELECT ISNULL(sub.id,'Total') AS "id",
sub.Adata,
sub.Bdata,
sub.Cdata
FROM (
SELECT A.id,
SUM(A.Adata) AS Adata,
SUM(B.Bdata) AS Bdata,
SUM(C.Cdata) AS Cdata
FROM TableA A
JOIN TableB B ON A.id = B.id
JOIN TableC C ON A.id = C.id
GROUP BY A.id WITH ROLLUP) sub
您应该使用内部联接。 Union (All) 似乎没有必要,除非某些表中缺少某些 ID:
Select coalesce(cast(i.id as varchar(10)), 'SUM')
, isnull(sum(A.data), '')
, isnull(sum(B.data), '')
, isnull(sum(C.data), '')
From (Select id From A
Union Select id From B
Union Select id From C
) as i
left Join A on A.id = i.id
left Join B on B.id = i.id
left Join C on C.id = i.id
group by grouping sets (i.id, ())
分组集添加总行
这可以解决您的问题。
select id,Adata,Bdata,SUM(Cdata) as Cdata
from ((select id,Adata,SUM(Bdata) as Bdata
from (A join B using(id)) group by id)T join C using(id))
group by id
这可能不是一个合适的答案。
你在混淆概念。 UNION ALL 是很少需要和使用的东西。将相似的结果集粘合在一起时会用到它。这里不是这种情况。
为了连接 tables,您当然应该使用连接。您使用 GROUP BY(您的案例中的 ID)声明的每个组都会得到一个结果行。您使用 SUM、MAX、COUNT 等聚合函数来聚合数据。
要编写的查询取决于是否所有 ID 都出现在 table A 和其他 table 中。区别主要是当时使用的连接类型。
ID 必须出现在所有 table 中:
select id, sum(a.adata), sum(b.bdata), sum(c.cdata)
from a
join b using (id)
join c using (id)
group by id;
ID 必须在 table 中唯一:
select id, sum(a.adata), coalesce(sum(b.bdata),0), coalesce(sum(c.cdata),0)
from a
left join b using (id)
left join c using (id)
group by id;
ID 不必存在于任何特定的 table:
select id, coalesce(sum(a.adata),0), coalesce(sum(b.bdata),0), coalesce(sum(c.cdata),0)
from a
full outer join b using (id)
full outer join c using (id)
group by id;
编辑:我应该补充一点 SQL 服务器不支持 USING 子句(这是标准的 SQL2003)。您可以将其替换为 ON 子句,只要您不需要完全外部联接就很容易,如果没有 using 子句则要复杂得多。
并且:通过使用 group by rollup(id)
而不是仅使用 group by id
,您会在最后得到一个总和行。
获得所需的输出(使用 SUM 行)
SELECT CAST(A.id AS VARCHAR(100)) AS ID,
(SELECT SUM(Aa.Adata) FROM TableA Aa WHERE A.id = Aa.id GROUP BY Aa.id) AS Adata,
(SELECT SUM(Ba.Bdata) FROM TableB Ba WHERE B.id = Ba.id GROUP BY Ba.id) AS Bdata,
(SELECT SUM(Ca.Cdata) FROM TableC Ca WHERE C.id = Ca.id GROUP BY Ca.id) AS Cdata
FROM TableA A
INNER JOIN TableB B ON A.id = B.id
INNER JOIN TableC C ON A.id = C.id
GROUP BY A.id, B.id, C.id
UNION ALL
SELECT CAST('SUM' AS VARCHAR(100)),
SUM(A.Adata), (SELECT
SUM(B.Bdata)
FROM TableB B), (SELECT
SUM(C.Cdata)
FROM TableC C)
FROM TableA A
输出:
ID Adata Bdata Cdata
1 8383 11251 2856
2 2707 6335 1364
3 6181 9632 4476
4 6708 11355 11384
SUM 23979 38573 20080
SQL Fiddle: http://sqlfiddle.com/#!3/ba58d/11/0