2013-05-10 91 views
2

我有一個查詢這是一個有點像這樣:返回一個值,即使在一個子查詢,其中返回空集

SELECT ISNULL(MyColumn, "Not Applicable") As MyColumn 
FROM MyTable 
WHERE SomeOtherColumn = 
(SELECT AValue 
FROM SomeOtherTable 
WHERE SomeConditionHolds 
) 

如果MyColumn相關值具有的價值,我得到這個,如果它爲空,則會根據需要給出「不適用」。

但是,偶爾子查詢返回空集,在這種情況下,整個查詢也返回空集。我仍然希望它返回「不適用」。

我已經能夠做的最好的是添加到上面

UNION 
SELECT 'Not Applicable' AS MyColumn 
WHERE NOT EXISTS 
    (SELECT AValue 
FROM SomeOtherTable 
WHERE SomeConditionHolds 
) 

但這種感覺真的哈克和低效。我希望有人有一個更好的主意。

+1

您可以運行先用結果去到一個臨時表或表變量選擇,然後檢查'@@ RowCount'。如果它爲零,則返回N/A行,否則返回臨時結果。 – HABO 2013-05-10 19:23:04

+0

這一直停滯不前,上面的問題只是一個更大問題的一個步驟,我發現了一個完全不同的解決方案。然而,在這個過程中,我確實嘗試了回答中提到的兩種類型的連接,並且當子查詢部分返回空集時,它們仍然返回emtpy集合。所以我不覺得我可以接受任何答案。感謝您的嘗試。 – cobaltduck 2013-05-18 18:59:19

回答

0

試試這個:

SELECT Case When T.AValue Is Null Then 'Not Applicable' Else MyColumn End As MyColumn 
    FROM MyTable Left Outer Join 
    (SELECT AValue 
    FROM SomeOtherTable 
    WHERE SomeConditionHolds 
    ) T on MyTable.SomeOtherColumn = T.AValue 
+0

我想你應該添加不同.. – Sunny 2013-05-10 19:24:53

+0

沒有什麼不同存在,當結果爲空值沒有行存在,ISNULL不適用,您的查詢的結果可能是所有行!!!(左連接返回所有左表的行沒有右表條件) – mojtaba 2013-05-10 19:31:32

+0

但我認爲這不是必要的。 – 2013-05-10 19:32:12

0

得到查詢結果,並在不存在行設置結果爲「不適用」,否則,您必須仔細檢查和廢物處理系統時間。

0

由於您的子查詢返回一個值,你可以很容易地將它轉換爲外連接,這將永遠給你一個行,這樣也會使查詢更高效,更優雅:

SELECT 
    ISNULL(MyColumn, "Not Applicable") As MyColumn 
FROM MyTable 
LEFT JOIN SomeOtherTable 
    ON SomeOtherColumn = AValue 
    AND SomeConditionHolds 

最關鍵的事情這裏是SomeConditionHolds加入的條件,不是的where子句,否則左連接有效成爲內連接。

+0

我認爲當MyTable返回NO行時,OP會要求提供解決方案。在這種情況下,您的LEFT JOIN將會空着。 – 2013-05-11 04:32:33

+0

@ G.Stoynev否 - 它可能沒有行的* joined *表(來自子查詢)。 OP說**但是,偶爾子查詢返回空集,在這種情況下整個查詢也返回空集。**。這個查詢解決了這個問題,完全恕我直言。 – Bohemian 2013-05-11 05:04:58

+0

那麼,他的主要謂詞是「Where SomeOtherColumn = '。子查詢NOT返回值意味着他的主謂詞返回false,這反過來意味着他的MyTable *應該*不返回任何行。而且我覺得他證實了我對他做UNION的方式的解釋。 – 2013-05-11 05:08:31

1
SELECT ISNULL(MyColumn, DummyCol) As MyColumn 
FROM MyTable 
    RIGHT OUTER JOIN (SELECT 'Not Available' AS DummyCol) Q ON DummyCol IS NOT NULL 
    AND SomeOtherColumn = 
    (SELECT AValue 
    FROM SomeOtherTable 
    WHERE SomeConditionHolds 
    ) 
0
declare @Foo as Table (FooId Int Identity, Something VarChar(16)); 
insert into @Foo (Something) values 
    ('One'), ('II'), ('3'); 

declare @FooLimit as Int = 1; -- Try 5. 

with Alicia as (
    select FooId, Something, 1 as SetId 
    from @Foo 
    where FooId >= @FooLimit 
    union all 
    select 42, 'n/a', 2) 
    select FooId, Something 
    from Alicia 
    where SetId = (select Min(SetId) from Alicia)