从具有保留顺序的内部查询中选择有限的字段集

时间:2014-03-18 13:06:27

标签: postgresql postgresql-9.1

我有一个SQL查询涉及与ORDER BY子句的一对多关系:

SELECT 
  s0_.id,
  s0_.created_at,
  s5_.sort_order
FROM 
  surveys_submits s0_
  INNER JOIN surveys_answers s3_ ON s0_.id = s3_.submit_id
  INNER JOIN surveys_questions s4_ ON s3_.question_id = s4_.id 
  INNER JOIN surveys_questions_references s5_ ON s4_.id = s5_.question_id 
ORDER BY 
  s0_.created_at DESC, 
  s5_.sort_order ASC

此查询返回以下结果:

id  | created_at          | sort_order
----+---------------------+-----------
218 | 2014-03-18 12:21:09 | 1
218 | 2014-03-18 12:21:09 | 2
218 | 2014-03-18 12:21:09 | 3
218 | 2014-03-18 12:21:09 | 4
218 | 2014-03-18 12:21:09 | 5
217 | 2014-03-18 12:20:57 | 1
217 | 2014-03-18 12:20:57 | 2
217 | 2014-03-18 12:20:57 | 3

             ...

214 | 2014-03-18 12:18:01 | 4
214 | 2014-03-18 12:18:01 | 5
213 | 2014-03-18 12:17:48 | 1
213 | 2014-03-18 12:17:48 | 2
213 | 2014-03-18 12:17:48 | 3
213 | 2014-03-18 12:17:48 | 4
213 | 2014-03-18 12:17:48 | 5

现在,我需要修改此查询,以便从保留顺序的开头返回前25个不同的ID。

我尝试过这样的事情:

SELECT DISTINCT id
FROM (
   SELECT ... ORDER BY ...
) inner_query
ORDER BY created_at DESC, sort_order ASC
LIMIT 25 OFFSET 0;

但显然它不起作用:

ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 16:       created_at DESC, 
               ^
********** Error **********

...我无法将created_atsort_order列添加到SELECT子句,因为它会导致重复的ID,就像第一个查询一样。

1 个答案:

答案 0 :(得分:2)

select *
from (
    SELECT distinct on (s0_.id)
        s0_.id,
        s0_.created_at,
        s5_.sort_order
    FROM 
        surveys_submits s0_
        INNER JOIN surveys_answers s3_ ON s0_.id = s3_.submit_id
        INNER JOIN surveys_questions s4_ ON s3_.question_id = s4_.id 
        INNER JOIN surveys_questions_references s5_ ON s4_.id = s5_.question_id 
    ORDER BY
        s0_.id,
        s0_.created_at DESC, 
        s5_.sort_order ASC
) s
order by
    created_at desc,
    sort_order ASC
limit 25

From the manual

  

SELECT DISTINCT ON(expression [,...])仅保留给定表达式求值的每组行的第一行。使用与ORDER BY相同的规则解释DISTINCT ON表达式(参见上文)。注意"第一行"除非使用ORDER BY来确保首先出现所需的行,否则每个集合都是不可预测的。