Технически это происходит потому, что оптимизатор считает WHERE x.item > '0'::bigint
гораздо более эффективным фильтром, чем information.type = 'task'. Таким образом, при сканировании таблицы условие WHERE x.item > '0'::bigint
выбирается в качестве предиката. Это мышление не является неправильным, но заставит вас впасть в эту, казалось бы, нелогичную проблему.
Предложение Гордона использовать CASE WHEN inf.type = 'task' THEN i.information::bigint END
может этого избежать, но, тем не менее, иногда оно может разрушить вашу идею поставить это под запрос и требуют, чтобы одно и то же условие было написано дважды.
Забавный трюк, который я пытался использовать OUTER APPLY:
SELECT x.* FROM (SELECT 1 AS dummy) dummy
OUTER APPLY (
SELECT information.id as id, item.information::bigint AS item
FROM information
INNER JOIN item
ON information.id = item.informationid
WHERE information.type = 'task'
) x
WHERE x.item > '0'::bigint
Извините, что я проверил только версию сервера SQL этого , Я понимаю, что PostgreSQL не имеет ВНЕШНЕГО ПРИМЕНЕНИЯ, но эквивалент должен быть:
SELECT x.* FROM (SELECT 1 AS dummy) dummy
LEFT JOIN LATERAL (
SELECT information.id as id, item.information::bigint AS item
FROM information
INNER JOIN item
ON information.id = item.informationid
WHERE information.type = 'task'
) x ON true
WHERE x.item > '0'::bigint
(ссылка этот вопрос )
Наконец, более аккуратно, но менее гибкий метод - добавить подсказку оптимизатора, чтобы отключить ее, чтобы оптимизатор запустил запрос так, как он написан.