Почему 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.