Почему count (*) возвращает несколько результатов в этом подзапросе (postgresql)? - PullRequest
1 голос
/ 20 марта 2012

Я хочу сгруппировать результаты запроса 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;

РЕДАКТИРОВАТЬ Ответ Андомара также позволил мне найти следующий подход (в двух словах адаптированный из примера в SQL (О'Рейли)).Это позволяет мне иметь сегменты в одном столбце со строкой для каждой пары групп / ответов.Я думал, что включу это для любого с этим вариантом использования:

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);

Ответы [ 2 ]

6 голосов
/ 20 марта 2012

Вы выбираете каждую строку из 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

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

3 голосов
/ 20 марта 2012

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

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

SELECT 'John Doe' FROM orders

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

SELECT 'John Doe'

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

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

...