SQL Server:逻辑等效于所有查询

时间:2009-11-25 13:16:27

标签: sql sql-server-2008

我有以下查询(简化):

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 ( ... ),因为更改顶级选择可能会在其他条件为添加到顶级位置。

5 个答案:

答案 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过滤掉“空”设置案例。