Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
连接表值参数-Sql Server T Sql_Sql_Sql Server_Tsql_Join - Fatal编程技术网

连接表值参数-Sql Server T Sql

连接表值参数-Sql Server T Sql,sql,sql-server,tsql,join,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

我有一个接受表值参数的存储过程。仅当该表有值时,我才希望与该表进行联接

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

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

如果这是我过去遇到的问题,那么它会很慢,因为这里有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
你可以尝试一种新方法

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

如果该表有值,您希望与该表进行联接是什么意思。与其先检查值,不如直接加入它。你会进行不必要的检查。通过检查值,您已经在访问该表。在这种情况下,您还可以继续使用表执行联接或子查询。也许你可以采取不同的方法。你打算做什么?您的目标或最终目标是什么?问题是我的查询不是这样简单的,它有大约10个select子查询作为列,我必须对大多数子查询应用此筛选器。我不确定我是否可以在这里使用IF语句。为什么不能?如果TVP有行,则执行一个复杂查询,否则执行另一个查询。然后优化器可以为执行的查询选择最佳计划。好的,谢谢您的尝试。我不想重复几乎相同的逻辑两次,只是在外部连接逻辑上有所不同。但我想这是SQL的发展方向。好吧,值得注意的是,我们之间的区别在于内部连接。然后它可以使用索引,这使它更快。我不知道外太空人是否也有同样的好处。它可能取决于您的数据库和键/索引。哦,如果您有一组这样的过滤器,您的另一个选择是创建动态sql。您确实需要注意这些事情的安全性,但是动态创建sql,然后使用exec_sql执行它可能会真正提高性能。不过,它也可能会把它储存起来,所以你只能试一下,看看效果如何。如果不了解更多关于数据库的信息,很难说这会很好