简体   繁体   中英

How can I create a conditional WHERE clause in SQL Server that returns multiple values?

I have the following SQL code for a SSRS report. I simplified the code because the original query is much longer. There is a parameter @ARTICLE which a user can input. What I want to do is create a conditional WHERE statement. If a user enters an article number (@ARTICLE) the query should filter ID's from Table1 that match with ID's for which the entered article number (@ARTICLE) have a match with a 'detailcode' from another table. If there is no article number given, do not filter (or skip the whole WHERE statement)

With the code below I get the following error:

Subquery returned more than 1 value. This is not permitted when the subquery follows =, ,=, <, <=, >. >= or when the subquery is used as an expression.'

Logically it works perfectly fine without the CASE statement, so when only the subquery is used to check for matching ID's. However, I only want to return matching IDs if the @ARTICLE parameter has a value. If it is NULL or an empty string I want to return all IDs (or just skip the entire WHERE statement). How can I include a condition in the WHERE clause that allows multiple rows to return given the example below?

I feel like my approach is way to complicated, any help is much appreciated!

DECLARE @ARTICLE AS VARCHAR(50) = '1234567'

SELECT * FROM Table1
    
WHERE 
Table1.ID IN (

CASE
    WHEN ISNULL(@ARTICLE,'')<>'' THEN
    (
    SELECT  ID
    FROM    Table2
    WHERE   detailcode IN (@ARTICLE)
    )
    ELSE Table1.ID
    END
    )

You're right, you're overcomplicating it a bit - if you look at the LIKE operator you can do something like:

DECLARE @filter NVARCHAR(50) = '123456';

DECLARE @f NVARCHAR(100) = '%' + @filter + '%';

SELECT * 
FROM [Table1] AS [t1]
     INNER JOIN [Table2] AS [t2]
                ON [t2].[joinField] = [t1].[joinField]
                   AND [t2].[detailCode] LIKE @f;

Where @filter is a parameter to the stored procedure.

Or to account for detailCode being null:

DECLARE @filter NVARCHAR(50) = '123456';

DECLARE @f NVARCHAR(100) = '%' + @filter + '%';

IF @filter != NULL    
     SELECT * 
     FROM [Table1] AS [t1]
          INNER JOIN [Table2] AS [t2]
                     ON [t2].[joinField] = [t1].[joinField]
                        AND [t2].[detailCode] LIKE @f;
 ELSE
     SELECT * 
     FROM [Table1] AS [t1]
          INNER JOIN [Table2] AS [t2]
                     ON [t2].[joinField] = [t1].[joinField];

I would check wether @ARTICLE is NULL or if it is NOT NULL and your subquery is fulfilled, like so:

WHERE
    ISNULL(@ARTICLE, '') = ''
    OR
    (
        ISNULL(@ARTICLE, '') <> ''
        AND ID IN
            (
                SELECT ID FROM Table2
                    WHERE detailcode = @ARTICLE
            )
    )

Maybe you can do it entire different, with an exists for example.
So you return all rows when @ARTICLE is null or '' OR exists at least one row in table2 with this article
The OR will have the effect that no filtering is done when the variable is null or ''

DECLARE @ARTICLE AS VARCHAR(50) = '1234567'

select t1.*
from   table1 t1
where  ( isnull(@ARTICLE, '') = ''
         or
         exists ( select 1 from table2 t2 where t2.detailcode = @ARTICLE )
       ) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM