2013-05-10 76 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)