2013-04-26 55 views
4

高水平行的獨特的計數:選擇參考

我有清單和檢查清單有檢查單項目。我想得到已經完成的清單的數量。具體而言,具有清單項目但全部完成的清單。

表:

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' 

問題這個問題是,它不排除部分完成的清單。

+0

更新問題要指出的是,不受任何檢查單項目中引用清單應排除在外。 – 2013-04-26 17:50:13

回答

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)。

+0

非常感謝Erwin。有時候,我不知道有多少PostgreSQL的在野外實際上是從你的答案在SO ... – 2013-04-26 20:43:52

+2

@AndrewHubbs得出:先生,你似乎是藝術奉承的大師。 – 2013-04-26 20:58:56

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 

您可以運行子查詢,看看有多少不完整的項目有每個檢查列表。

+0

謝謝戈登。你的回答讓我找到了解決方案。所需的唯一更改是子選擇內的「GROUP BY cl.id」。否則Postgres會拋出一個錯誤。 – 2013-04-26 18:50:51

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 
+0

好點。我想** **不含任何項目的**清單。 – 2013-04-26 17:49:28

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 
1

嘗試:

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

+1這非常優雅。但是,'HAVING'條款不起作用。 'min(boolean_col)'沒有被執行。另外,'='t''只是Postgres中適當布爾類型的噪聲。我冒昧地更新了一個有效的'HAVING'條款。如果您不同意,請隨時回滾。 – 2013-04-26 20:47:08

+0

@ErwinBrandstetter:這是沒有測試查詢 - 德哦!感謝編輯。 – 2013-04-27 08:16:05