根据where子句中的参数从表中选择

时间:2017-05-24 11:30:48

标签: sql sql-server where

我正在编写一个“简单”的SQL函数来选择数据,具体取决于WHERE子句中的参数:

DECLARE @csp AS CHAR(1) = 'F'

SELECT  [NUMERO_DOSSIER]
FROM    [dbo].[Dossier]
WHERE   
    [CSP] IN
    (
        CASE @csp
            WHEN 'F' THEN
                (SELECT [CSP] FROM [dbo].[CSP_1])
            WHEN 'N' THEN
                (SELECT [CSP] FROM [dbo].[CSP_2])
            END
    )

根据SQL Server 2012,此查询没有语法错误。但运行它会返回此错误:

  

Msg 512,Level 16,State 1,Line 2子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

根据我的理解,这里的问题是:CASE函数返回标量,并且不能返回表。

如何重写它以使其有效?

3 个答案:

答案 0 :(得分:2)

不要在CASE子句中使用WHERE - 它通常会使逻辑更复杂。只需将逻辑扩展为布尔逻辑:

WHERE ( @csp = 'F' AND [CSP] IN (SELECT [CSP] FROM [dbo].[CSP_1]) ) OR
      ( @csp = 'N' AND [CSP] IN (SELECT [CSP] FROM [dbo].[CSP_2]) ) 

答案 1 :(得分:2)

一种方法是使用UNION ALL子查询:

SELECT  [NUMERO_DOSSIER]
FROM    [dbo].[Dossier]
WHERE   
    [CSP] IN
    (
        SELECT [CSP] 
        FROM [dbo].[CSP_1]
        WHERE @csp = 'F'
        UNION ALL
        SELECT [CSP] 
        FROM [dbo].[CSP_2]
        WHERE @csp = 'N'
    );

答案 2 :(得分:1)

使用两个CTE和两个JOIN操作:

DECLARE @csp AS CHAR(1) = 'F'

;WITH Table1 AS (
    SELECT [CSP] 
    FROM [dbo].[CSP_1]
), Table2 AS (
    SELECT [CSP] 
    FROM [dbo].[CSP_2]
)
SELECT  [NUMERO_DOSSIER]
FROM  [dbo].[Dossier] AS d
JOIN Table1 AS t1 ON @csp = 'F' AND d.CSP = t1.CSP
JOIN Table2 AS t2 ON @csp = 'N' AND d.CSP = t2.CSP

修改

看到@ Dan的回答后,这可能更干净了:

;WITH Table1 AS (
    SELECT [CSP] 
    FROM [dbo].[CSP_1]
    WHERE @csp = 'F'
), Table2 AS (
    SELECT [CSP] 
    FROM [dbo].[CSP_2]
    WHERE @csp = 'N'
)
SELECT  [NUMERO_DOSSIER]
FROM  [dbo].[Dossier] AS d
JOIN Table1 AS t1 ON d.CSP = t1.CSP
JOIN Table2 AS t2 ON d.CSP = t2.CSP