如果所有列值都为true,则返回true

时间:2012-10-22 15:55:15

标签: sql postgresql aggregate-functions exists boolean-logic

PostgreSQL中有一种更快的方法可以基本上在几行中执行if吗?

说我有一张桌子

ticket | row | archived
1      | 1   | true
1      | 2   | true
1      | 3   | true
2      | 1   | false
2      | 2   | true

有什么方法可以在ticket =的列下面做一个if语句? 因此,如果<= p>,则ticket = 1将成立

true && true && true = true

并且ticket = 2将为false,因为

false && true = false

或者我应该坚持使用

SELECT ( (SELECT COUNT(*) FROM table WHERE ticket = 1)
       = (SELECT COUNT(*) FROM table WHERE ticket = 1 AND archived = true) )

3 个答案:

答案 0 :(得分:15)

聚合函数bool_and()

简单,简洁,清晰。

SELECT bool_and(archived)
FROM   tbl
WHERE  ticket = 1;

我引用手册here

true if all input values are true, otherwise false

子查询表达式EXISTS - 与@Mike provided

类似

更快。但是,您必须另外检查是否存在ticket = 1的任何行,或者您对不存在的票证的结果不正确:

SELECT EXISTS (SELECT 1 FROM tbl WHERE ticket=1)
       AND NOT
       EXISTS (SELECT 1 FROM tbl WHERE ticket=1 AND archived = FALSE);

索引

两种形式都可以并且将使用如下索引:

CREATE index tbl_ticket_idx ON tbl (ticket);

..这使得两者都快,但EXISTS查询更快,因为一旦找到第一个匹配的行,此表单就可以停止扫描。两个查询之间几乎没有任何区别,每个票证只有几行,但每张票证的许多行存在实质性差异。

要在第9.2页中使用仅索引扫描,您需要multi-column index的格式:

CREATE index tbl_ticket_archived_idx ON tbl (ticket, archived);

这个更好 任何情况下大多数情况和任何版本的PostgreSQL。由于data alignment,在索引中向boolean添加integer不会使索引增长。几乎没有任何成本增加了好处。

但是,索引列会阻止HOT(Heap Only Tuple)更新。假设UPDATE仅更改列archived。如果该列未被任何索引使用(以任何方式),则可以对该行进行HOT更新。否则,不能采用这种快捷方式。我写了more on HOT updates in this related answer

因此,一如既往,这完全取决于您的确切工作量。

答案 1 :(得分:5)

如下:

select not exists (select 1 from table where ticket=1 and not archived)

我认为这可能比计算count may or may not use an index更有利,而且您需要知道的是,任何 FALSE行是否存在那张票。我认为只在ticket创建一个部分索引可能会非常快。

SQL Fiddle

答案 2 :(得分:1)

select not false = any (
        select archived
        from foo
        where ticket = 1
    )

SQL Fiddle