Postgresql неверное значение COUNT () при левом внешнем соединении - PullRequest
0 голосов
/ 26 марта 2020

У меня проблемы с агрегатом подсчета при использовании LEFT OUTER JOIN в postgresql 9.3.

Когда я делаю стандартный оператор без левого внешнего соединения, он возвращает правильный счет, в данном случае 3. Когда оператор становится более сложным, как приведенный ниже, он возвращает 7, что неверно.

Только некоторые из агрегатов count () неверны, большинство из них верны. Чем это вызвано? Должен ли я использовать другое соединение?

SELECT country_code, 
       period, 
       COUNT(commissions.id) AS count, 
       SUM(commissions.total) AS total, 
       SUM(CASE WHEN commission_adjustments.is_bonus is True THEN commission_adjustments.total else 0 END) AS bonus
FROM commissions 
  LEFT OUTER JOIN commission_adjustments ON commissions.id = commission_adjustments.commission_id
GROUP BY commissions.country_code, commissions.period 
ORDER BY commissions.country_code, commissions.period

Ответы [ 2 ]

0 голосов
/ 26 марта 2020

COUNT() подсчитывает количество не NULL значений. Самое простое решение для того, что вы хотите, - это использовать COUNT(DISTINCT):

   COUNT(DISTINCT commissions.id) AS count, 

. Это хорошо работает, если счетчик мал, а размеры немного (здесь есть одно измерение). В других случаях вам нужно объединить данные до присоединения .

0 голосов
/ 26 марта 2020

Если у вас есть это:

SELECT * FROM table
id, x
1, 'foo'
2, 'foo'
3, 'foo'

SELECT x, COUNT(*) as ct FROM table GROUP BY x
x, ct
'foo', 3

И это "правильно" ..

И тогда вы делаете это:

SELECT x, COUNT(*) as ct FROM table LEFT JOIN sometable ON table.x = sometable.y GROUP BY x

И это внезапно "идет неправильно ":

x, ct
'foo', 7

Это потому, что есть декартово произведение; более одного ряда sometable соответствует этому ряду. Удалите группировку / поместите выделение * и посмотрите:

SELECT * FROM table LEFT JOIN sometable ON table.id = sometable.otherid --GROUP BY x

id, x, otherid
1, 'foo', 1
1, 'foo', 1
1, 'foo', 1
2, 'foo', 2
2, 'foo', 2 
2, 'foo', 2
3, 'foo', null

7 строк, вызвано:

SELECT * FROM othertable
otherid
1
1
1
2
2
2

Более одной строки из othertable соответствует строке в table

Вам нужно либо ограничить ваше объединение, чтобы оно не вызывало это умножение строк, либо, возможно, сгруппировать соединяющиеся строки в подзапросе перед выполнением объединения

Переключение типа JOIN может также привести к появлению большего количества строк, если вдруг не все строки будут соответствовать друг другу, но это не повлияет на этот случай, когда вы считаете таблицу слева и добавляете другую через левое соединение; только картезианские продукты будут поднимать вещи здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...