簡體   English   中英

SQL 服務器 select 語句的問題

[英]Issue with SQL Server select statement

我需要 select 語句的幫助,我目前正在努力解決這個問題。 場景是這樣的:

select * 來自 mytable WHERE isActive=1

  1. 如果僅提供 id,則 select id=@id 的所有內容
  2. 如果提供了 firstname 和 lastname,則 select firstname=@firstname 和 lastname=@lastname 的所有內容,無論 ID
  3. 如果提供了 firstname 或 lastname,則 select firstname=@firstname 或 lastname=@lastname 的所有內容再次與 ID 無關
  4. 如果提供了 id、firstname 和 lastname,則只需 select 其中 firstname=@firstname 和 lastname=@lastname 再次與 ID 無關

這是我的查詢:

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)

不知何故,我沒有得到預期的結果,例如,當我同時提供名字和姓氏時,它會顯示每個人的名字,而不管他們的姓氏如何:-(

請幫忙

不確定您是否需要工會,尤其是 UNION ALL,但您有兩個選擇。 第一個很漂亮,它適用於小型數據集。 第二個選項看起來很難看,但幾乎可以保證為您提供最佳性能。

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;

除非您可以描述它,否則#2和#4之間沒有區別。

請嘗試以下方法。 雖然WHERE子句謂詞不是 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);

可以將這些寫為一個查詢,但由於使用索引的方式,它可能會導致低效的表掃描。 因此,您最好使用UNION ALL來加入單獨的查詢:

;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);

UNKNOWN位向編譯器提示您不知道可能輸入的內容,並且不應保留第一次運行的參數值(參數嗅探)。

另一種提示是OPTION(RECOMPILE) ,這意味着查詢將在每次運行時重新編譯。 不過,這有開銷。

將其寫為一系列 IF 語句:

--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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM