在单个查询中查找两个不相关表中的计数

时间:2012-12-31 07:20:05

标签: sql postgresql join count aggregate-functions

以下查询用于计算单个查询中两个不相关表中的行数。

  With t1 as (Select 1 
              Union Select  2 
              Union Select 3),
  t2 as (Select 'A' 
         Union Select 'B')

  Select (Select count(*) from t1), (Select count(*) from t2)

是否有更好的方法可以避免选择查询中的两个select语句。

输出应为

3 2

任何特定于Postgres的构造也会这样做。

3 个答案:

答案 0 :(得分:3)

简单而正确

首先,您可以使用VALUES表达式而不是更详细的UNION ALL SELECT来简化测试用例
如果数据类型不是默认的integertext,那么您需要在第一行显式类型转换。

其次,FULL OUTER JOIN完全没有意义。它所做的就是让你的查询更慢。如果任何行在另一个表中有多个匹配,则它会在计数中相乘。

WITH t1(col1, col2) AS (VALUES (1, 1),   (2, 2),   (3, 3))
    ,t2(col1, col2) AS (VALUES (1, 'A'), (2, 'B'), (2, 'C'))  -- 2nd row for "2"
SELECT count(t1.*), count(t2.*)
FROM t1
FULL OUTER JOIN t2 USING (col1);

收率:

4   3

错误

WITH t1(col2) AS (VALUES (1),   (2),   ( 3))
    ,t2(col2) AS (VALUES ('A'), ('B'), ('C'))
SELECT (SELECT count(*) FROM t1) AS t1_ct
      ,(SELECT count(*) FROM t1) AS t2_ct;

收率:

3   3

正确,除了更简单,更快 不可否认,新申请row_number(),就不会有愚蠢行为。但这只是浪费时间。

性能

大桌子的计数相对较慢。如果您不需要完全计数但可以使用估算值,那么您可以非常快速地实现这一目标:

SELECT reltuples::bigint AS estimate
FROM   pg_class
WHERE  oid = 'myschema.mytable'::regclass;

我引用the manual here

  

它由VACUUM,ANALYZE和一些DDL命令更新,例如   创建指数。

More details in this related answer.

答案 1 :(得分:0)

计数是一项非常昂贵的操作(就CPU负载而言)。尽可能避免。如果您需要在没有任何条件的情况下获取表的总行数,则某些RDBMS会提供一种解决方法,例如:使用MSSQL,它是这样的:

select SUM(row_count) as Total_Rows
 from sys.dm_db_partition_stats
where object_name(object_id) = 'YourTableName' 
  and index_id < 2

另一种方法是将您的点数保存在单独的表格中,例如如果您需要按特定值分组的总数。您可以使用触发器增加和减少计数。如果您(例如)必须始终在主表单上显示计数(活动用户,每个区域的活动帖子等),则建议使用此方法。

答案 2 :(得分:-2)

通过添加row_number列并执行完全外部联接来介绍两个表之间的关系。

  With t1 as (Select 1 as Col1, 1 
              Union Select  2, 2 
              Union Select 3, 3),
  t2 as (Select -1 as Col1, 'A' 
         Union Select -2, 'B')

  Select count(t1.*), count(t2.*) from t1 full outer join t2 on t1.Col1 = t2.Col1