I need help with a select statement that I'm currently struggling with. The scenario is this:
select * from mytable WHERE isActive=1
Here's my query:
DECLARE @ID INT =25,
@firstname NVARCHAR(100),
@lastname NVARCHAR(100);
SELECT * from mytable
where isActive=1
and ( ID = -1 or ID = @ID)
or (firstname = @firstname)
or (lastname = @lastname)
or (firstname = @firstname and lastname = @lastname)
somehow I'm not getting the results expected, for example when I provide both firstname and lastname, it shows everyone with the firstname regardless of their lastname:-(
Please help
Not sure if you need a union, especially UNION ALL, but you have two choices. First one is pretty, it works with small data sets. The second option looks ugly, but gives you almost guaranteed best performance.
SELECT * FROM mytable WHERE isActive=1
AND (
(@ID IS NOT NULL AND @firstname IS NULL AND @lastname IS NULL AND @ID = ID) OR
(@firstname IS NOT NULL AND @lastname IS NOT NULL AND firstname=@firstname and lastname=@lastname) OR
(@firstname IS NOT NULL AND @lastname IS NULL AND firstname=@firstname) OR
(@firstname IS NULL AND @lastname IS NOT NULL AND lastname=@lastname)
)
IF @ID IS NULL AND @firstname IS NULL AND @lastname IS NULL
SELECT * FROM mytable WHERE isActive=1;
IF @ID IS NOT NULL AND @firstname IS NULL AND @lastname IS NULL
SELECT * FROM mytable WHERE isActive=1 AND @ID = ID;
IF @firstname IS NOT NULL AND @lastname IS NOT NULL
SELECT * FROM mytable WHERE isActive=1 AND firstname=@firstname AND lastname=@lastname;
IF @firstname IS NOT NULL AND @lastname IS NULL
SELECT * FROM mytable WHERE isActive=1 AND firstname=@firstname;
IF @firstname IS NULL AND @lastname IS NOT NULL
SELECT * FROM mytable WHERE isActive=1 AND lastname=@lastname;
That is with no difference between #2 & #4, unless you can describe it.
Please try the following method. Though the WHERE
clause predicates are not SARGable.
SQL
DECLARE @ID INT =25
, @firstname NVARCHAR(100) = NULL
, @lastname NVARCHAR(100) = NULL;
SELECT *
FROM mytable
WHERE isActive = 1
AND ID = COALESCE(@ID, -1) -- or COALESCE(@ID, ID) depending on the logic
AND firstname = COALESCE(@firstname, firstname)
AND lastname = COALESCE(@lastname, lastname);
It is possible to write these as one query, but owing to the way indexes are used, it will probably result in an inefficient table scan. Therefore you are best off using UNION ALL
to join the separate queries:
;WITH cte AS (
select * from mytable WHERE isActive=1
)
SELECT *
FROM cte
WHERE firstname = @firstname AND @lastname IS NULL
UNION ALL
SELECT *
FROM cte
WHERE lastname = @lastname AND @firstname IS NULL
UNION ALL
SELECT *
FROM cte
WHERE firstname = @firstname AND lastname = @lastname
UNION ALL
SELECT *
FROM cte
WHERE ID = @ID
AND @firstname IS NULL AND AND @lastname IS NULL
OPTION(OPTIMIZE FOR UNKNOWN);
The UNKNOWN
bit hints to the compiler that you don't know what may be entered, and it shouldn't keep the parameter values from the first run (parameter sniffing).
An alternative hint is OPTION(RECOMPILE)
, which means the query will be recompiled on every run. This has overhead, though.
Write it as a series of IF statements:
--Test #1
DECLARE @ID INT = 25, @firstname NVARCHAR(100) = 'Florian', @lastname NVARCHAR(100) = 'Voss';
IF (@firstname IS NOT NULL AND @lastname IS NOT NULL)
SELECT *
FROM [AdventureWorks2019].[Person].[Person]
WHERE (firstname = @firstname AND lastname = @lastname)
IF @firstname IS NOT NULL AND @lastname IS NULL
SELECT *
FROM [AdventureWorks2019].[Person].[Person]
WHERE (firstname = @firstname)
GO
--Test #2
DECLARE @ID INT = 25, @firstname NVARCHAR(100) = 'Florian', @lastname NVARCHAR(100) = NULL;
IF (@firstname IS NOT NULL AND @lastname IS NOT NULL)
SELECT *
FROM [AdventureWorks2019].[Person].[Person]
WHERE (firstname = @firstname AND lastname = @lastname)
IF (@firstname IS NOT NULL AND @lastname IS NULL)
SELECT *
FROM [AdventureWorks2019].[Person].[Person]
WHERE (firstname = @firstname)
GO
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.