SQL Server:来自第一个查询的空行集的辅助查询

时间:2012-01-30 19:43:56

标签: sql sql-server

说我有以下简单的表格

表p {    id int,    pointId int,    state int,    值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中执行此操作,那将是非常好的。 任何建议或指示都会很棒!

谢谢,

A

3 个答案:

答案 0 :(得分:2)

这是维护和性能方面的最佳答案。 来源: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
    );

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

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