使用子查询中的属性进行比较

时间:2018-04-03 11:03:35

标签: sql postgresql

我有以下查询,它基本上告诉我与他所做的考试相关的用户的状态:

SELECT users.id, 
CASE WHEN users.closed_at IS NOT NULL 
       THEN 'closed'
     WHEN COUNT(exams.id) FILTER(users.closed_at IS NOT NULL OR requests.finished_at IS NOT NULL) = COUNT(exams.id)
       THEN 'completed'
     WHEN COUNT(exams.id) FILTER(users.closed_at IS NOT NULL OR requests.finished_at IS NOT NULL) = 0
       then 'not-completed'
     ELSE 'in-progress' 
END AS user_status
LEFT JOIN exams ON exams.user_id = users.id

这很好用,但现在我也希望能够根据用户的考试状态进行过滤,同时考虑到我应该能够按多种状态进行过滤。我被建议用子查询做这个,所以假设我想找到考试状态已关闭或“未完成”的用户,我试过这个:

SELECT users.id, 
    CASE WHEN users.closed_at IS NOT NULL 
           THEN 'closed'
         WHEN COUNT(exams.id) FILTER(users.closed_at IS NOT NULL OR requests.finished_at IS NOT NULL) = COUNT(exams.id)
           THEN 'completed'
         WHEN COUNT(exams.id) FILTER(users.closed_at IS NOT NULL OR requests.finished_at IS NOT NULL) = 0
           then 'not-completed'
         ELSE 'in-progress' 
    END AS user_status
    LEFT JOIN exams ON exams.user_id = users.id
    WHERE (
      SELECT 
       CASE WHEN users.closed_at IS NOT NULL 
           THEN 'closed'
         WHEN COUNT(exams.id) FILTER(users.closed_at IS NOT NULL OR requests.finished_at IS NOT NULL) = COUNT(exams.id)
           THEN 'completed'
         WHEN COUNT(exams.id) FILTER(users.closed_at IS NOT NULL OR requests.finished_at IS NOT NULL) = 0
           then 'not-completed'
         ELSE 'in-progress' 
         END AS user_status_in_inner_query
    ) user_status_in_inner_query = 'closed' OR user_status_in_inner_query = 'not-completed'

但它抛出一个错误,说“在WHERE中不允许聚合函数”。我怎么能这样做?

2 个答案:

答案 0 :(得分:1)

我希望这样的东西能起作用吗?

SELECT id, user_status
FROM (
        SELECT users.id, 
        CASE WHEN users.closed_at IS NOT NULL 
               THEN 'closed'
             WHEN COUNT(exams.id) FILTER(users.closed_at IS NOT NULL OR requests.finished_at IS NOT NULL) = COUNT(exams.id)
               THEN 'completed'
             WHEN COUNT(exams.id) FILTER(users.closed_at IS NOT NULL OR requests.finished_at IS NOT NULL) = 0
               then 'not-completed'
             ELSE 'in-progress' 
        END AS user_status
        LEFT JOIN exams ON exams.user_id = users.id
) xx
WHERE user_status IN ('closed', 'not-completed')

基本上只需将原始查询作为子查询,并使用您想要的任何过滤器对其进行标准选择。

答案 1 :(得分:1)

不要在WHERE子句中重复查询,将所有内容放入派生表中,然后可以使用别名:

select *
from (
  SELECT users.id, 
         CASE 
            WHEN users.closed_at IS NOT NULL THEN 'closed'
            WHEN COUNT(exams.id) FILTER(users.closed_at IS NOT NULL OR requests.finished_at IS NOT NULL) = COUNT(exams.id)
              THEN 'completed'
            WHEN COUNT(exams.id) FILTER(users.closed_at IS NOT NULL OR requests.finished_at IS NOT NULL) = 0
              then 'not-completed'
            ELSE 'in-progress' 
         END AS user_status
  FROM users --<<< Seems to be missing in your query
     LEFT JOIN exams ON exams.user_id = users.id
) t
where user_status in ('closed', 'not-completed');