如何在单个查询中计算与基表结果匹配的多个表的记录?

Posted

技术标签:

【中文标题】如何在单个查询中计算与基表结果匹配的多个表的记录?【英文标题】:How to count records of multiple tables that match the results of a base table in a single query? 【发布时间】:2018-07-05 10:12:51 【问题描述】:

下面的查询返回所有procedures表的名称和table1中匹配结果的个数,如下:

SELECT p.name, COUNT(t1.id) as Quantity
FROM procedures p
LEFT JOIN table1 t1
ON p.id = t1.id
GROUP BY p.name ASC

如何进行上面的查询,但要计算许多其他表?想象一下,我还有 2 个表要计数,查询输出如下所示的列:

Name Quantity1 Quantity2 Quantity3
A        0       100        27
B        10      0          15
C        50      200        1

程序表:

id   name
1     A
2     B
3     C

我想根据过程统计匹配结果的其他表

table1、table2、table3...

id   name
1     A
1     A
1     A
2     B
2     B
3     C
3     C

【问题讨论】:

样本数据和期望的结果会有所帮助。重复使这变得棘手。 我放了一些示例数据以使其更易于理解。 【参考方案1】:

也加入其他表:

SELECT p.name, 
       COUNT(t1.id) as Quantity1, 
       COUNT(t2.id) as Quantity2,
       COUNT(t3.id) as Quantity3
FROM   procedures p
       LEFT JOIN table1 t1 ON p.id = t1.id
       LEFT JOIN table2 t2 ON p.id = t2.id
       LEFT JOIN table3 t3 ON p.id = t3.id
GROUP  BY p.name ASC

【讨论】:

我尝试了您的解决方案,显示已按我的意愿完成,但计数值很奇怪,看起来一列正在影响其他列的计数,例如: Quantity1 的过程 A 等于20,这个值是正确的,但是在 Quantity 2 相同的过程 A 应该等于 5,出现为 20,重复 Quantity2 的相同值。您是否知道如何单独进行所有这些计数,而不会在列之间产生任何干扰?【参考方案2】:

最好的办法大概是在join之前聚合:

SELECT p.name, SUM(t1.cnt1) as cnt1
FROM procedures p LEFT JOIN
     (SELECT t1.id, COUNT(*) as cnt1
      FROM table1 t1
      GROUP BY t1.id
     ) t1
     ON p.id = t1.id
GROUP BY p.name ASC;

嗯,如果 nameid 不是 1-1,你仍然会得到重复。如果这是一个问题,那么:

SELECT p.name, t1.cnt1 as cnt1
FROM (SELECT DISTINCT name
      FROM procedures p
     ) p LEFT JOIN
     (SELECT p.name, COUNT(*) as cnt1
      FROM table1 t1 JOIN
           procedures p
           ON p.id = t1.id
      GROUP BY p.name
     ) t1
     ON p.name = t1.name;

这种方法可以安全地泛化。

【讨论】:

以上是关于如何在单个查询中计算与基表结果匹配的多个表的记录?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle(创建视图)

SQL 视图

使用二级索引改进数据访问DynamoDB

简述oracle视图

Doris -- Rollup和物化视图

SQL 视图