我有以下查询(简化):
SELECT
Id
FROM
dbo.Entity
WHERE
1 = ALL (
SELECT
CASE
WHEN {Condition} THEN 1
ELSE 0
END
FROM
dbo.Related
INNER JOIN dbo.Entity AS TargetEntity ON
TargetEntity.Id = Related.TargetId
WHERE
Related.SourceId = Entity.Id
)
其中{Condition}
是TargetEntity
上的复杂动态条件。
简单来说,此查询应返回所有相关实体符合所需条件的实体。
不幸的是,这不能很好地工作,因为当1 = ALL
应用于空集时,SQL标准TRUE
的计算结果为ALL
。我知道我可以添加AND EXISTS
,但这需要我重复整个子查询,我相信这会导致性能问题。
我应该如何重写查询以实现我需要的结果(SQL Server 2008)?
提前致谢。
注意:实际上,整个查询都是高度动态的,因此完美的解决方案是仅重写1 = ALL ( ... )
,因为更改顶级选择可能会在其他条件为添加到顶级位置。
答案 0 :(得分:2)
难道你不能用min来实现这个目标吗?
EG:
SELECT
Id
FROM
dbo.Entity
WHERE
1 = (
SELECT
MIN(CASE
WHEN {Condition} THEN 1
ELSE 0
END)
FROM
dbo.Related
INNER JOIN dbo.Entity AS TargetEntity ON
TargetEntity.Id = Related.TargetId
WHERE
Related.SourceId = Entity.Id
)
如果没有子句,min应该返回null,如果它们都是1,则返回1,如果有0,则返回0,并且与1相比,只应该为1。
答案 1 :(得分:0)
它可以翻译为pick Entities where no related entities with unmatched condition exist
。
这可以通过以下方式实现:
SELECT
Id
FROM
dbo.Entity
WHERE
NOT EXISTS (
//as far as I have an element which do not match the condition, skip this entity
SELECT TOP 1 1
FROM
dbo.Related
INNER JOIN dbo.Entity AS TargetEntity ON
TargetEntity.Id = Related.TargetId
WHERE
Related.SourceId = Entity.Id AND
CASE
WHEN {Condition} THEN 1
ELSE 0
END = 0
)
编辑:视情况而定,你可以写下这样的东西:
WHERE Related.SourceId = Entity.Id AND NOT {Condition}
如果它不会改变查询的复杂性。
答案 2 :(得分:0)
不使用all
,而是更改查询以直接比较子查询的结果:
select Id
from dbo.Entity
where 1 = (
select
case
when ... then 1
else 0
end
from ...
where ...
)
答案 3 :(得分:0)
可能这会起作用:WHERE NOT 0 = ANY(...)
答案 4 :(得分:0)
如果我正确阅读了查询,可以将其简化为:
SELECT e.Id
FROM dbo.Entity e
INNER JOIN dbo.Related r ON r.SourceId = e.Id
INNER JOIN dbo.Entity te ON te.Id = r.TargetId
WHERE <extra where stuff>
GROUP BY e.Id
HAVING SUM(CASE WHEN {Condition} THEN 1 ELSE 0 END) = COUNT(*)
这表示条件必须对所有行都为真。它使用INNER JOINs过滤掉“空”设置案例。