选择引用的唯一行数

时间:2013-04-26 17:42:52

标签: sql postgresql select

高级别:

我有清单和清单都有清单项目。我想得到已经完成的清单数量。具体而言,具有核对表项目但已全部完成的核对清单。

表格

Table "checklists"

|     Column   |          Type          |
+--------------+------------------------+
| id           | integer                |
| name         | character varying(255) |

Table "checklist_items"

|     Column   |          Type          |
+--------------+------------------------+
| id           | integer                |
| completed    | boolean                |
| name         | character varying(255) |
| checklist_id | integer                |

问题: 什么查询会给我完整的清单计数?具体而言,要小心排除包含完整和不完整的清单项目的清单以及没有清单项目的清单。

到目前为止已经尝试过:

SELECT DISTINCT COUNT(DISTINCT "checklists"."id")
  FROM "checklists"
INNER JOIN "checklist_items" ON "checklist_items"."checklist_id" = "checklists"."id"
  WHERE "checklist_items"."completed" = 't'

此问题的问题在于它不会排除部分完成的核对表。

5 个答案:

答案 0 :(得分:4)

更快,但是:

SELECT count(DISTINCT i.checklist_id)
FROM   checklist_items i
LEFT   JOIN checklist_items i1 ON i1.checklist_id = i2.checklist_id
                              AND i.completed IS NOT TRUE
WHERE i.completed
AND   i1.checklist_id IS NULL;

这仅收集存在已完成项目的清单 并排除存在未完成的另一个checklist_item的那些(FALSENULL)。

答案 1 :(得分:2)

以下使用子查询执行此操作:

select COUNT(*)
from (select cl.id,
             SUM(case when cli.completed <> 't' or cli.completed is null then 1 else 0 end) as NumIncomplete
      from checklists cl join
           checklist_items cli
           ON cli.checklist_id = cl.id
      group by cl.id
     ) t
where NumIncomplete = 0

您可以运行子查询以查看每个检查列表中有多少不完整的项目。

答案 2 :(得分:1)

尝试:

SELECT COUNT(*)
FROM   (
         SELECT 1
         FROM checklist_items
         GROUP BY checklist_id
         HAVING bool_and(completed)
       ) as sq

答案 3 :(得分:0)

假设空清单被认为已完成(尽管您可以修改此清单以删除空清单)。

SELECT checklists.id 
FROM checklists LEFT JOIN (SELECT DISTINCT checklist_id 
                           FROM checklist_items WHERE completed = 'f') partial_checklists 
                ON checklists.id = partial_checklists.checklist_id 
WHERE partial_checklists.checklist_id = NULL

要排除空的清单(虽然我不确定这里的语法):

SELECT checklists.id 
FROM checklists LEFT JOIN (SELECT checklist_id 
                           FROM checklist_items WHERE completed = 'f' 
                         UNION DISTINCT 
                           SELECT checklist_id 
                           FROM checklist_items 
                           GROUP BY checklist_id 
                           HAVING count(*) = 0) partial_checklists 
                  ON checklists.id = partial_checklists.checklist_id 
WHERE partial_checklists.checklist_id = NULL

答案 4 :(得分:0)

select count(*) completed_items
from (
    select
        c.id, c.name, count(*) total_items
    from
        checklists c
        inner join
        checklist_items ci on c.id = ci.checklist_id
    group by c.id, c.name
    having count(!completed or null) = 0
) s