Возвращает true, если все значения столбцов true

есть ли более быстрый способ в PostgreSQL по существу сделать if на нескольких строках?

скажем у меня есть таблица

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

есть ли способ сделать оператор if через столбец, где ticket = ? Так что, где ticket = 1 было бы верно, потому что

true && true && true = true

и где ticket = 2 будет ложным, потому что

false && true = false

или я должен просто палка с

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

3 ответов


Агрегатная функция bool_and()

просто, коротко, ясно.

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

я цитирую руководство здесь:

true if all input values are true, otherwise false

выражение вложенного запроса EXISTS - как @Mike при условии

быстрее. Но вы должны дополнительно проверить, есть ли строки с 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 запрос быстрее, потому что эта форма может остановить сканирование, как только будет найдена первая соответствующая строка. Вряд ли существует какая-либо разница между двумя запросами с несколькими строками на билет, но существенный разница для многих строк за билет.

использовать сканирование в pg 9.2 вам понадобится многостолбцовый индекс вида:

CREATE index tbl_ticket_archived_idx ON tbl (ticket, archived);

это лучше на в любом случае большинство случаев и любая версия PostgreSQL. Из-за выравнивание данных добавление boolean до integer в индексе не заставит индекс расти вообще. Добавленное преимущество для едва ли любой цены.

однако индексированные столбцы предотвращают горячее (только куча Кортеж) обновления. Скажи UPDATE изменяется только столбец archived. Если столбец не используется каким-либо индексом (каким-либо образом), строка может быть обновлена. В противном случае, этот ярлык не может быть принят. Я написал больше о горячих обновлениях в этом соответствующем ответе.

Итак, как всегда, все зависит от вашей точной нагрузки.


как насчет чего-то вроде:

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

Я думаю, что это может быть выгодно по сравнению с сравнением подсчетов, как count может или не может использовать индекс и в самом деле все, что вам нужно знать, если любой FALSE строки существуют для этого билета. Я думаю, просто создав частичный индекс на ticket может быть невероятно быстрым.

SQL Fiddle


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

SQL Fiddle