在不使用子查询的情况下使用 SELECT DISTINCT ON 计算总行数
Posted
技术标签:
【中文标题】在不使用子查询的情况下使用 SELECT DISTINCT ON 计算总行数【英文标题】:Counting the total number of rows with SELECT DISTINCT ON without using a subquery 【发布时间】:2018-01-09 13:15:19 【问题描述】:我使用 PostgreSQL SELECT DISTINCT ON
语法执行了一些查询。我想让查询在每个结果行旁边返回总行数。
假设我有一张表my_table
,如下所示:
CREATE TABLE my_table(
id int,
my_field text,
id_reference bigint
);
然后我有几个值:
id | my_field | id_reference
----+----------+--------------
1 | a | 1
1 | b | 2
2 | a | 3
2 | c | 4
3 | x | 5
基本上my_table
包含一些版本化数据。 id_reference
是对数据库全局版本的引用。对数据库的每次更改都会增加全局版本号,并且更改总是会向表中添加新行(而不是更新/删除值),并且它们会插入新的版本号。
我的目标是执行一个只检索表中最新值以及总行数的查询。
例如,在上述情况下,我想检索以下输出:
| total | id | my_field | id_reference |
+-------+----+----------+--------------+
| 3 | 1 | b | 2 |
+-------+----+----------+--------------+
| 3 | 2 | c | 4 |
+-------+----+----------+--------------+
| 3 | 3 | x | 5 |
+-------+----+----------+--------------+
我的尝试如下:
select distinct on (id)
count(*) over () as total,
*
from my_table
order by id, id_reference desc
这会返回几乎正确的输出,除了 total
是 my_table
中的行数而不是结果查询的行数:
total | id | my_field | id_reference
-------+----+----------+--------------
5 | 1 | b | 2
5 | 2 | c | 4
5 | 3 | x | 5
(3 rows)
如您所见,它具有5
,而不是预期的3
。
我可以通过使用子查询和count
作为聚合函数来解决这个问题:
with my_values as (
select distinct on (id)
*
from my_table
order by id, id_reference desc
)
select count(*) over (), * from my_values
这会产生我预期的输出。
我的问题:有没有办法避免使用这个子查询并让类似于count(*) over ()
的东西返回我想要的结果?
【问题讨论】:
我不确定在这种情况下您是否可以避免子查询。您需要在某处获得中间结果才能使用COUNT(*) OVER ()
从实际查询中获取行数。
【参考方案1】:
您正在查看my_table
3 种方式:
-
为每个
id
查找最新的id_reference
为每个id
查找最新的id_referenc
emy_field
统计表中id
s 的不同数量
因此我更喜欢这个解决方案:
select
c.id_count as total,
a.id,
a.my_field,
b.max_id_reference
from
my_table a
join
(
select
id,
max(id_reference) as max_id_reference
from
my_table
group by
id
) b
on
a.id = b.id and
a.id_reference = b.max_id_reference
join
(
select
count(distinct id) as id_count
from
my_table
) c
on true;
这有点长(尤其是我编写 SQL 的长而细的方式),但它清楚地说明了正在发生的事情。如果你在几个月后回来(通常有人会这样做),那么你会花更少的时间来了解发生了什么。
最后的“on true”是一个经过深思熟虑的笛卡尔积,因为子查询“c”只能有一个结果,而您确实想要一个带有它的笛卡尔积。
子查询不一定有问题。
【讨论】:
这不能回答我的问题。您刚刚用大部分标准 sql 重写了distinct on
。以上是关于在不使用子查询的情况下使用 SELECT DISTINCT ON 计算总行数的主要内容,如果未能解决你的问题,请参考以下文章
在不使用 Union ALL 的情况下添加多个 select 语句