选择子查询结果以及其他字段的计数

时间:2018-12-10 23:50:28

标签: sql postgresql

我目前有一个查询,该查询选择父资源的不同ID,同时能够过滤和排序其子表的结果。查询的基本结构如下:

SELECT s.id
FROM (
    SELECT DISTINCT ON (work_items.id) work_items.id, work_item_states.id AS work_item_states_id
    FROM work_items
    JOIN work_item_states ON work_item_states.work_item_refer = work_items.id
    WHERE work_item_states.disposition = 'cancelled'
    ORDER BY work_items.id
) AS s
ORDER BY s.work_item_states_id DESC
LIMIT 50
OFFSET 0

注意:此查询中的列,过滤器,联接等仅是出于说明目的的示例。这些查询将完全不同,因为它们支持任意数据。只有查询的基本结构保持不变。

出于分页的目的,我需要能够计算子查询的总结果。现在,我只是使用一个完整的单独查询,如下所示,与上面的示例相同:

SELECT COUNT(s)
FROM (
    SELECT DISTINCT ON (work_items.id) work_items.id, work_item_states.id AS work_item_states_id
    FROM work_items
    JOIN work_item_states ON work_item_states.work_item_refer = work_items.id
    WHERE work_item_states.disposition = 'cancelled'
    ORDER BY work_items.id
) AS s

这是相当低效的,因为我将使用具有数百万个条目的数据库。有谁知道我如何组合这两种查询,以便结果返回ID和子查询的计数? 像这样:

SELECT s.id, COUNT(s)

是我要寻找的,但是结果中每个ID的计数仅为1。

谢谢

1 个答案:

答案 0 :(得分:1)

使用窗口功能可以(最简单)进行此操作。接受您的初始查询,而忽略其中的具体细节:

SELECT s.id, s.total_item_count
FROM (
    SELECT DISTINCT ON (work_items.id) work_items.id
     , work_item_states.id AS work_item_states_id
     , count(work_items.id) over () as total_item_count
    FROM work_items
    JOIN work_item_states ON work_item_states.work_item_refer = work_items.id
    WHERE work_item_states.disposition = 'cancelled'
    ORDER BY work_items.id
) AS s
ORDER BY s.work_item_states_id DESC
LIMIT 50
OFFSET 0

请注意,在group bydistinct on构造之后(甚至在使用having子句过滤之后),窗口函数也被应用在 之后。子查询返回的行数,而不是work_items的工作表中与work_item_states联接的行数,然后才采用不同的行或其他聚合。因此,您实际上可以在窗口函数中使用聚合函数。