【问题标题】:SQL Server: Secondary query on empty rowset from first querySQL Server:从第一个查询对空行集进行辅助查询
【发布时间】:2015-05-27 22:04:41
【问题描述】:

假设我有以下简单的表格

表一个 { id int, pointId int, 状态整数, 价值整数 }

id    pointId     state   value
-------------------------------
1     1           2       xxxxx
2     3           2       xxxxx
3     3           2       xxxxx
4     3           1       xxxxx

使用以下两个查询:

SELECT * FROM a WHERE state = 1 and pointId = x
SELECT * FROM a WHERE state = 2 and pointId = x

有没有办法组合这两个查询,以便:

  • 如果查询 1 返回 >0 行,则返回查询 1 的结果
  • 如果查询 1 返回 0 行,则返回查询 2 的结果

(因此对于 pointId = 1 它将返回第 1 行,对于 pointId = 3 它将返回第 4 行)

我一直在尝试将两者与一个联合做类似的事情

SELECT * FROM a WHERE state = 1 AND pointId = x
UNION ALL
SELECT * FROM a WHERE state = 2 AND pointId = x and 
pointId NOT IN (SELECT pointId FROM a WHERE state = 1 AND pointId = x)

我想知道我是否让这种方式变得复杂,是否有更简单的方法。我意识到我可以只运行第一个查询,然后在我的代码中处理它,但如果我能在 sql 中执行此操作会非常好。 任何建议或指示都会很棒!

谢谢,

一个

【问题讨论】:

  • 在这种情况下您不应该使用 UNION。您不希望合并记录 - 您希望根据 EXISTS 处理查询 1 或查询 2。

标签: sql sql-server


【解决方案1】:

这是维护和性能方面的最佳答案。 来源:https://stackoverflow.com/a/12981314

WITH query1 AS (
    SELECT ...
),
query2 AS (
    SELECT ...
)
SELECT *
    FROM query1
UNION ALL
SELECT *
    FROM query2
    WHERE NOT EXISTS (
        SELECT NULL
        FROM query1
    );

【讨论】:

    【解决方案2】:

    UNION 用于组合元组,您的规范提到您要返回一组元组或另一组元组。这种情况下不想使用UNION,可以使用EXISTS

    IF EXISTS(...insert your first query here...)
        BEGIN
           --a record exists process first query
        END
    ELSE
        BEGIN
             --do other query
        END
    

    【讨论】:

    • Right:) 但是,那会执行两次查询,不是吗?我的示例中的表 a 实际上是一个巨大的表,我想知道是否有办法避免两次查询...(但已经非常感谢了!)
    • 您没有处理或返回EXISTS 子句。您正在检查记录是否存在。您还可以做的是检查计数是否 > 0 SELECT COUNT(*) FROM Query1,如果返回 > 0,则执行查询 1,否则执行查询 2。
    【解决方案3】:

    对于您问题中的具体情况,您可以这样做

    WITH T
         AS (SELECT *,
                    DENSE_RANK() OVER (ORDER BY state) AS R
             FROM   a
             WHERE  state IN ( 1, 2 )
                    AND pointId = x)
    SELECT id,
           pointId,
           state,
           value
    FROM   T
    WHERE  R = 1; 
    

    更一般地说,如果查询 1 可能很昂贵,您可以执行它,然后检查@@ROWCOUNT 以了解是否执行查询 2。

    这意味着您的应用程序需要处理多个结果集。如果您不想处理可以将第一个查询插入到表变量中的问题,那么您只需执行 SELECT 即可,如果 @@ROWCOUNT > 0

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-03
      • 2016-08-10
      相关资源
      最近更新 更多