使用索引通过多列之一进行SELECT

时间:2015-01-07 01:51:06

标签: sql-server

我有这张桌子:

    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

...虽然当前查询扫描速度较慢。

第二个查询速度很快,但并不像我需要的那样工作。

是否有办法允许绕过一个或另一个参数,同时仍使用索引搜索?

4 个答案:

答案 0 :(得分:0)

在sql命令(link)中使用CASEWHENTHEN。希望它有所帮助。

答案 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种可能的情况。

  • parm1 set,parm2 -1(忽略)
  • parm1 -1(忽略),parm2 set
  • parm1 set,parm2 set
  • parm1 -1(忽略),parm2 -1(忽略)< - 返回所有行

所以我用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块语句总是进行扫描,并杀死性能。