我有一个接受表值参数的存储过程。我希望只有在具有值的情况下才能与该表联接。
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更快的选择?我有一个复杂的查询,我不得不在多个地方使用这个过滤器,这会减慢查询速度。
答案 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