2012-01-30 41 views
0

说我有以下简单的表格SQL服务器:从第一次查询的空行集二次查询

表 { ID INT, 点名INT, 状态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

(所以点名= 1,它将返回第1行中,点名= 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中执行此操作,那将非常好。 任何建议或指针会很好!

感谢,

一个

+0

你不应该在这种情况下使用UNION。您不想将记录组合​​起来 - 您正在寻找基于'EXISTS'处理查询1或查询2。 – JonH 2012-01-30 19:48:45

回答

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 
+0

对:)但是,这将执行查询两次否?我的例子中的表a实际上是一个巨大的表,我想知道是否有办法避免两次查询......(但是非常感谢!) – user1178830 2012-01-30 19:52:13

+0

您没有处理或返回“EXISTS”条款。您正在检查是否存在记录。你也可以做的是检查count> 0“SELECT COUNT(*)FROM Query1”,如果返回> 0,则执行查询1,否则执行查询2。 – JonH 2012-01-30 20:01:37

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

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 
    );