在Where子句中的COALESCE?

时间:2014-03-25 00:35:47

标签: sql sql-server-2008 stored-procedures

如果列匹配,是否有一种在SQL中表达以选择特定行的好方法,否则选择更一般的行?类似的东西:

SELECT name FROM names 
            WHERE (colA = @colA OR colA = 'ALL') 

我只是希望它返回一个特定记录(如果存在),否则返回通用“ALL”记录,如果它找不到特定的列匹配。似乎COALESCE与我正在寻找的类似,但我不知道这在语法上是如何工作的。

3 个答案:

答案 0 :(得分:3)

@Blorgbeard回答(使用top 1和order by)可能是最好的方法,但只是为了与众不同你也可以使用子查询而不存在:

SELECT name FROM names 
WHERE (colA = @colA) OR (colA = 'ALL' AND NOT EXISTS(
                                                SELECT name FROM names 
                                                WHERE colA = @colA)) 

我认为这样做的“好处”是它使用了更多的标准sql。

答案 1 :(得分:2)

这个查询虽然不算很好,但应该做你想做的事情:

SELECT TOP 1 name FROM names 
WHERE (colA = @colA OR colA = 'ALL') 
ORDER BY CASE WHEN colA='ALL' THEN 1 ELSE 0 END

编辑:对于多列,我认为你想要的是:

SELECT TOP 1 name FROM names 
WHERE (colA = @colA AND colB = @colB) OR (colA = 'ALL') 
ORDER BY CASE WHEN colA='ALL' THEN 1 ELSE 0 END

我假设只有一个ALL行,因此无需检查colB='ALL',并且该表的“密钥”为colA和{{ 1}}合并 - 因此您对colB匹配但colA不匹配的行不感兴趣。

答案 2 :(得分:0)

COALESCE在连接多个表时非常有用,并且您希望按特定顺序使用第一个非空值。

实施例

SELECT
   TheID=COALESCE(Table1.TheID,Table2.TheID,NULL)
FROM
   Table1 
   INNER JOIN Table2 ON Table1.TheID=Table2.TheID

除了您发布的示例之外,实现您所要求的一种替代方法是设置可为空的参数,并且仅在其具有值时匹配:

实施例

CREATE Test(@Param1 INT=NULL)
AS
SELECT
    *
FROM
    Table
WHERE
    (@Param1 IS NULL OR IDField=@Param1)

如果所有不匹配的记录都需要记录和匹配,那么我猜你可以自己加入表来获得匹配和不匹配。

SELECT
    Calc=CASE WHEN Table2.IDField IS NULL THEN Table.Value ELSE 'ALL' END
FROM
    Table
    INNER JOIN Table Table2 ON Table2.IDField<>@Param1
WHERE
    (Table.IDField=@Param1)