2012-01-30 40 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 
    );