SQL - 左连接分组
Posted
技术标签:
【中文标题】SQL - 左连接分组【英文标题】:SQL - Group By with Left Join 【发布时间】:2011-03-14 23:59:04 【问题描述】:我有两张桌子。表 A 有一个员工姓名列表。表 B 是一个复杂的表,其中包含有关员工拨打的电话的信息。
我的目标是制作一个包含“name”和“callCount”列的表格。我的目标是通过“左加入”和“分组依据”来做到这一点,但我一直想念那些没有打电话的员工。我怎样才能让它保留名称并在那里放一个零?
也许我很接近,有人可以指出我的错字?提前感谢您的帮助,这里是 SQL:
SELECT A.name, COUNT(B.call_id) AS 'outgoing call count'
FROM EmployeeTable A
LEFT JOIN CallTable B
ON A.name = B.call_from_name
WHERE B.call_type LIKE 'outgoing'
AND B.voice_mail = '0'
...
GROUP BY A.name
【问题讨论】:
【参考方案1】:这是一个 JOIN 而不是 NULL 问题:您的过滤器正在将 OUTER 更改为 INNER JOIN。这意味着您只会在 CallTable (B) 中有行的地方获得 COUNT,而不是您想要的 OUTER JOIN。
SELECT A.name, COUNT(B.call_id) AS 'outgoing call count'
FROM
EmployeeTable A
LEFT JOIN
(
SELECT call_from_name, call_id FROM CallTable
WHERE call_type LIKE 'outgoing'
AND voice_mail = '0'
AND /* other CallTable filters */
) B
ON A.name = B.call_from_name
WHERE
/* only EmployeeTable A filters */
GROUP BY A.name
编辑:在您在别处发表评论后,您对 B 的所有过滤器都必须在派生表中,而不是在外部 where。
【讨论】:
当您不需要通配符比较时,请小心使用 LIKE。它真的可以杀死你的查询速度。只需进行常规相等比较: WHERE call_type = 'outgoing' 进一步解释:wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN 非常感谢,自从过去 4 小时以来我一直在挣扎。终于解决了。再次感谢 感谢您的回答。我在几秒钟内就得到了结果,并且很好地使用了这个示例【参考方案2】:因为您使用的是 LEFT JOIN,所以对 LEFT JOIN 中定义的表的引用可以为空。行在那里,你只是没有看到计数值为零。这意味着您需要将此 NULL 值转换为零(在这种情况下):
SELECT A.name,
COALESCE(COUNT(B.call_id), 0) AS 'outgoing call count'
FROM EmployeeTable A
LEFT JOIN CallTable B ON B.call_from_name = A.name
AND B.call_type LIKE 'outgoing'
AND B.voice_mail = '0'
WHERE ...
GROUP BY A.name
此示例使用COALESCE,这是一种处理 NULL 值的 ANSI 标准方法。它将返回第一个非空值,但如果找不到,它将返回空值。 ISNULL 是 SQL Server 上的一个有效替代方案,但它不能移植到其他数据库,而 COALESCE 可以。这是an MSDN article comparing the two functions。
【讨论】:
不需要 COALESCE:它是 B 上的 WHERE 子句过滤器,使其成为 INNER JOIN 我试过 ISNULL 和 COALESCE,都给出了相同的结果。我可能做错了什么?我的 where 子句比我列出的要多,但它们都是确定计数所必需的。以上是关于SQL - 左连接分组的主要内容,如果未能解决你的问题,请参考以下文章
在两个表上分组并在结果VBA ADODB SQL查询上执行左连接