Postgresql的COUNT()值不正确,带有左外部联接



在postgresql 9.3中使用LEFT OUTER JOIN时,计数聚合出现问题。

当我执行一个没有左外部联接的标准语句时,它会返回正确的计数,在本例中为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

COUNT()统计非NULL值的数量。最简单的解决方案是使用COUNT(DISTINCT):

COUNT(DISTINCT commissions.id) AS count, 

如果计数很小,并且维度很少(这里只有一个维度(,则此操作效果良好。在其他情况下,您可能希望在加入之前聚合数据

如果你有这个:

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

这是因为存在笛卡尔乘积;多于一行的CCD_ 4与该行匹配。删除分组/选择*并查看:

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类型也会导致出现更多的行,但这不会影响这种情况,即计算左侧的表并通过左侧联接添加另一个表;只有笛卡儿积会在中起作用

相关内容

  • 没有找到相关文章