我有这张桌子:
CREATE TABLE [Person].[Address](
[AddressID] [int] NOT NULL,
[AddressLine1] [nvarchar](60) NOT NULL,
[StateProvinceID] [int] NOT NULL,
CONSTRAINT [PK_Address_AddressID] PRIMARY KEY CLUSTERED
(
[AddressID] ASC
)
)
GO
使用这个额外的非聚集索引。
CREATE UNIQUE NONCLUSTERED INDEX [IX_Address_AddressLine1_StateProvinceID
ON [Person].[Address]
(
[AddressLine1] ASC,
[StateProvinceID] ASC,
)
GO
我正在使用现有的应用代码。该应用程序将两个参数传递给我的查询,但其中一个可能等于' -1'。如果是这样,目的是匹配该参数的所有行。
当前查询如下所示:
Select AddressID, AddressLine1, StateProvinceID
From Person.Address
Where ((AddressID = @AddressID) or (@AddressID=-1))
and ((StateProvinceID = @StateProvinceID) or (@AddressID=-1))
当@AddressID或@StateProvinceID等于' -1'时返回所需的数据,它基本上是忽略的(-1 = -1返回TRUE)
麻烦就是索引。当我这样做时,它会进行扫描,而不是搜索。
返回搜索:
Select AddressID, AddressLine1, StateProvinceID
From Person.Address
Where AddressID = @AddressID
and StateProvinceID = @StateProvinceID
...虽然当前查询扫描速度较慢。
第二个查询速度很快,但并不像我需要的那样工作。
是否有办法允许绕过一个或另一个参数,同时仍使用索引搜索?
答案 0 :(得分:0)
在sql命令(link)中使用CASE
,WHEN
,THEN
。希望它有所帮助。
答案 1 :(得分:0)
Select AddressID, AddressLine1, StateProvinceID
From Person.Address
Where AddressID = CASE WHEN @AddressID = -1 THEN AddressID ELSE @AddressID END AND
StateProvinceID = CASE WHEN @StateProvinceID = -1 THEN StateProvinceID ELSE @StateProvinceID END
答案 2 :(得分:0)
我认为如果您更新具有列的索引:[AddressLine1]和[StateProvinceID]到[StateProvinceID]和[AddressLine1](将StateProvinceID放在索引中的第一个),查询应该使用此索引而不是全表扫描。
答案 3 :(得分:0)
似乎单个SQL语句中的分支逻辑将始终返回SCAN而不是SEEK。
我最终要做的就是编写显式(和丑陋)分支逻辑,为我想要的条件选择一个SIMPLE查询。
在我的例子中,有两个参数。目标是当给定参数= -1以匹配所有记录时,基本上忽略where子句中的该参数。
有两个参数,有4种可能的情况。
所以我用4 If语句编写了分支逻辑。
如果parm1<> -1和parm2 = -1
- then do a simple query that only uses parm1
如果parm1 = -1且parm2<> -1
- then do a simple query that only uses parm2
等...
虽然非常难看,但每次都会返回一个SEEK。丑陋但代码非常快。更漂亮的“When,Then,Else”SINGULAR块语句总是进行扫描,并杀死性能。