我希望弄清楚SQL语句中的HAVING组件是如何工作的,特别是对于具有多个连接的SQL语句。请考虑以下SQL select语句:
SELECT
p.id,
p.first_name as [First Name],
p.last_name as [Last Name]
FROM
( [tbl_person] as p
INNER JOIN [tbl_person_languages] as pl
ON [p].[id] = [pl].[person_id])
INNER JOIN [tbl_person_crossCuttingSkills] As ccp
ON [p].[id] = [ccp].[person_id]
WHERE
cint(pl.language_id) in (12,14) AND
cint(ccp.skill_id) in (55)
GROUP BY
p.id,
p.first_name,
p.last_name
HAVING
count(pl.language_id) =2 AND
count(ccp.skill_id) = 1
我想从tbl_person中提取记录,其中记录具有所有WHERE要求。例如:我想选择所有使用意大利语(ID 12)和西班牙语(ID 15)并且具有烹饪技巧(55)的用户。他们需要满足所有要求,而不仅仅是一个或多个要求。我假设这是你使用GROUP BY和HAVING的地方。随着HAVING:
count(pl.language_id) =2
我使用count = 2,因为语言WHERE子句(12和14)中有两个选项
我用
count(ccp.skill_id) = 1
因为WHERE子句中有一个值(55)。
这是正确的方法吗?由于某种原因,这不返回任何记录(我的数据库中有一条记录符合这些要求的人)。但是,如果我改变我的HAVING:
count(pl.language_id) =2 AND
count(ccp.skill_id) = 2
工作正常。为什么是这样?我的假设是如何工作不正确还是还有其他事情发生?
答案 0 :(得分:1)
记住count()
的作用。 。 。它计算非NULL值。因此,您计算两个非NULL值,然后计数相同。
在SQL的大多数方言中,您可以通过执行以下操作来解决此问题:
HAVING count(distinct pl.language_id) = 2 AND count(distinct ccp.skill_id) = 1
但这在MS Access中不起作用,因为MS Access不支持COUNT(DISTINCT)
。
所以,你可能会更加冗长。在你的情况下:
HAVING SUM(iif(cint(pl.language_id) = 12, 1, 0)) > 0 AND
SUM(iif(cint(pl.language_id) = 14, 1, 0)) > 0 AND
SUM(iif(cint(ccp.skill_id) = 55, 1, 0)) > 0
对不起,这个HAVING
条款并不简单。您可以切换到与ANSI功能更紧密对齐的另一个数据库(例如SQL Server Express)。