在表值参数上加入 - Sql Server T SQL

时间:2016-01-15 21:03:29

标签: sql sql-server tsql join

我有一个接受表值参数的存储过程。我希望只有在具有值的情况下才能与该表联接。

CREATE PROC dbo.TestProc
    (@name UNIQUEIDENTIFIER = null,
     @hasCityGuids bit, 
     @cityGuids dbo.GUIDTableType READONLY)
AS
BEGIN
   SELECT x1 , x2
   FROM Address A
   WHERE (@hasCityGuids = 0 
          OR A.CityGuid IN (SELECT Value FROM @cityGuids)) 
END

另一种选择是进行外连接

SELECT 
    x1 , x2
FROM 
    Address A 
LEFT OUTER JOIN
    @cityGuids CG ON A.CityGuid = CG.Value

是否有比这2更快的选择?我有一个复杂的查询,我不得不在多个地方使用这个过滤器,这会减慢查询速度。

2 个答案:

答案 0 :(得分:1)

如果这是我过去遇到过的问题,那么因为OR在这里很慢而且优化器没有表现并使用索引

WHERE (@hasCityGuids = 0 OR A.CityGuid IN (
          Select Value from  @cityGuids )) 

相反,我们最终得到了一个实际的IF语句,比如

CREATE PROC dbo.TestProc( @name UNIQUEIDENTIFIER = null,
                          @hasCityGuids bit, 
                          @cityGuids dbo.GUIDTableType READONLY)
AS
BEGIN

   IF @hasCityGuids = 0 THEN
   BEGIN
   SELECT x1 , x2
   FROM Address A
   END
   ELSE
   SELECT x1 , x2
   FROM Address A INNER join @cityGuids CG ON A.CityGuid = CG.Value

END

答案 1 :(得分:0)

您可以尝试存在

BEGIN
   SELECT x1 , x2
   FROM Address A
   WHERE (@hasCityGuids = 0 
          OR EXISTS ( SELECT null FROM @cityGuids innerHolder where innerHolder.Value = A.CityGuid) 
END

您可以尝试将TVP值放入#temp表中,并在其水合后为其创建索引

IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
begin
    drop table #Holder
end


CREATE TABLE #Holder
(ID INT )


/* simulate your insert */
INSERT INTO #HOLDER (ID) 
select 1 union all select 2 union all select 3 union all select 4
/* 
select value from FROM @cityGuids 
*/


/* CREATE CLUSTERED INDEX IDX_TempHolder_ID ON #Holder (ID) */

CREATE INDEX IDX_TempHolder_ID ON #Holder (ID)




/* then try exists */

       SELECT x1 , x2
       FROM Address A
       WHERE (@hasCityGuids = 0 
              OR EXISTS ( SELECT null FROM #Holder innerHolder where innerHolder.Value = A.CityGuid) 

IF OBJECT_ID('tempdb..#Holder') IS NOT NULL
begin
    drop table #Holder
end