Почему count (*) возвращает несколько результатов в этом подзапросе (postgresql)?

Я хочу сгруппировать результаты запроса count (*) в ведра значений. Я тестирую это на базе данных dellstore2 postgresql. Мой запрос ниже возвращает правильные ответы, но делает это один раз для каждой строки таблицы (несколько тысяч идентичных результатов). Я могу исправить это, добавив LIMIT 1 конец запроса, но я хотел бы понять, почему я получаю дубликаты, если это указывает на более широкую проблему с моим подходом. Запрос:

SELECT
    (SELECT count(*)
        FROM
            orders
        WHERE
            totalamount > 0 AND totalamount <= 100) AS ">0 <= 100",
    (SELECT count(*)
        FROM
            orders
        WHERE
            totalamount > 100 AND totalamount <= 200) AS ">100 <= 200"
...
FROM
    orders;

ИЗМЕНИТЬ Ответ Andomar также позволил мне найти следующий подход (адаптированный из примера в SQL в двух словах (O'Reilly)). Это позволяет мне иметь ведра в одном столбце, с строкой для каждого спайка/ответа. Я думал, что включу его для кого-нибудь с этим прецедентом:

SELECT CASE
        WHEN totalamount IS NULL THEN 'Unknown'
        WHEN totalamount <= 100 THEN 'Not more than 100'
        WHEN totalamount <= 200 THEN 'Not more than 200'
        ELSE 'Over 200'
    END "Bucket",
    COUNT(*) "Number of results"
FROM
    orders
GROUP BY CASE
        WHEN totalamount IS NULL THEN 'Unknown'
        WHEN totalamount <= 100 THEN 'Not more than 100'
        WHEN totalamount <= 200 THEN 'Not more than 200'
        ELSE 'Over 200'
    END
ORDER BY
    MIN(totalamount);

Ответ 1

Вы выбираете каждую строку из orders, а затем для каждой строки оцениваете подзапросы.

Вместо этого рассмотрите этот подход:

select  count(case when 0 < totalamount and totalamount <= 100 then 1 end)
            as "<0,100]"
,       count(case when 100 < totalamount and totalamount <= 200 then 1 end)
            as "<100,200]"
from    Orders

Это вычисляло бы оба агрегата в одном сканировании таблицы.

Ответ 2

Потому что вы включили их в подзапрос. По внешнему виду оба подзапроса count выполняются для каждой строки таблицы orders. Если вы опустите часть from из основного запроса, вы должны получить только одну строку.

Например, запрос

SELECT 'John Doe' FROM orders

возвращает "John Doe" для каждой строки в таблице заказов.

SELECT 'John Doe'

выбирает только одну строку.

Отказ от ответственности: это поведение сервера sql.