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