SQL:包含&;排除在同一个字段上,而不是同时存在,在何处和不存在?
我在同一个SQL:包含&;排除在同一个字段上,而不是同时存在,在何处和不存在?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我在同一个role\u id字段中有需要包含和排除的内容,因此我为NOT EXISTS()子查询和内部联接调用同一个表 SELECT u.fname ,u.lname ,c.country ,c.postal FROM [user] u INNER JOIN company c ON (u.company_id = c.id) INNER JOIN users_roles ur ON (u.id = ur.user_id) WHERE ur.rol
role\u id
字段中有需要包含和排除的内容,因此我为NOT EXISTS()
子查询和内部联接调用同一个表
SELECT
u.fname
,u.lname
,c.country
,c.postal
FROM [user] u
INNER JOIN company c
ON (u.company_id = c.id)
INNER JOIN users_roles ur
ON (u.id = ur.user_id)
WHERE ur.role_id = 3
AND NOT EXISTS (SELECT 1
FROM users_roles
WHERE role_id = 4
AND user_id= u.id)
ORDER BY c.country, c.postal
这种方法很有效,但似乎有点笨重,所以我想知道是否有一种更标准(性能)的方法我不知道?我建议对两个查询都运行性能分析,但您也可以使用左外部联接来执行此操作
SELECT
u.fname
,u.lname
,c.country
,c.postal
FROM [user] u
INNER JOIN company c
ON (u.company_id = c.id)
INNER JOIN users_roles ur
ON (u.id = ur.user_id)
LEFT OUTER JOIN users_roles ur2
ON (u.id = ur2.user_id)
AND role_id = 4
WHERE ur.role_id = 3
AND ur2.user_id IS NULL
ORDER BY c.country, c.postal
如果在表中找不到匹配的行,这将以NULL
代替ur2
表的值结束;如果您在WHERE
子句中断言该值为NULL
,它将排除任何匹配项。您可以只加入用户角色一次,这可能会对性能有所帮助。我现在无法决定我更喜欢哪一个问题
SELECT
u.fname
,u.lname
,c.country
,c.postal
FROM [user] u
INNER JOIN company c
ON (u.company_id = c.id)
CROSS APPLY (
SELECT SUM (IIF(role_id = 3, 1, 0)) AS role3Count, SUM (IIF(role_id = 4, 1, 0)) AS role4Count
FROM users_roles ur
WHERE role_id BETWEEN 3 AND 4 AND u.id = ur.user_id
) ur
WHERE role3Count > 0 AND role4Count = 0
ORDER BY c.country, c.postal
这可能会稍微快一点,因为对用户角色
进行单个索引搜索,其范围角色id在3到4之间
就足以检索角色。在您的查询中,有两个搜索。另一方面,此查询执行一些聚合和计算。你需要测量一下
我不认为这是一个更好的问题。它比你的更复杂。不管怎样,我还是会提出的。您自己决定。这一个只进行一次连接,它使用分组、对角色ID求和并检查聚合结果,SQLFIDLE上的执行时间是6ms vs 24ms
SELECT
u.fname
,u.lname
,c.country
,c.postal
,sum(ur.role_id)
FROM [user] u
INNER JOIN company c
ON (u.company_id = c.id)
INNER JOIN users_roles ur
ON (u.id = ur.user_id)
and role_id in(3,4)
group BY u.fname, u.lname, c.country, c.postal
having sum(ur.role_id) = 3
go
它避免了子查询。根据数据和数据库软件(SQL Server/MySQL/Oracle/Postgres/etc),此查询可能会收到比基于子查询的方案更有效的计划。一般来说,JOIN
比子查询快。SQL Server不具备这种通用性。SQL Server将EXISTS
谓词转换为半联接。可能是这样,但请注意,我建议问题的作者对这两个查询进行分析,并且我以书面形式回答问题(即是否有其他方式编写查询)。