以下 T-SQL 查询在子查询的where子句中使用SubmittedBy.PartyId上的相关子查询。
此代码位于存储过程中,其中@SpecificBusinessGroup和@SpecificBusinessCategory是传递给存储过程的变量。如果变量作为null传入,则查询需要几秒钟才能运行。如果变量包含数据,则此查询需要一个多小时才能运行。这就是为什么我确定这个问题是针对这个相关子查询的原因。我需要帮助将其转换为JOIN的派生表,但是我很难过。
非常感谢任何帮助。非常感谢。
SELECT *
FROM
PremiumFinanceLoan pfl
LEFT JOIN CustomerAccount c ON pfl.CustomerAccountId = c.PartyId
LEFT JOIN Entity SubmittedBy ON c.SubmittedById = SubmittedBy.PartyId
LEFT JOIN ...
WHERE
(@SpecificBusinessGroup IS NULL OR @SpecificBusinessCategory IS NULL OR EXISTS
(
select null -- That way we will get one row for each group
from EntityBusinessCategoryMap as EBC
join BusinessCategory as BC on BC.BusinessCategoryId = EBC.BusinessCategoryId
join BusinessGroup as BG on BG.BusinessGroupId = BC.BusinessGroupId
where
(@SpecificBusinessGroup IS NULL OR
( EBC.EntityId = SubmittedBy.PartyId AND BG.BusinessGroupId = @SpecificBusinessGroup))
AND (@SpecificBusinessCategory IS NULL OR
( EBC.EntityId = SubmittedBy.PartyId AND BC.BusinessCategoryId = @SpecificBusinessCategory))
))
以下是我的解决方案,但我认为它不正确,我认为它不等同于相关子查询:
SELECT *
FROM
PremiumFinanceLoan pfl
LEFT JOIN CustomerAccount c ON pfl.CustomerAccountId = c.PartyId
LEFT JOIN Entity SubmittedBy ON c.SubmittedById = SubmittedBy.PartyId
LEFT JOIN
(
select ebc.EntityId
from EntityBusinessCategoryMap ebc
join BusinessCategory bc on bc.BusinessCategoryId = ebc.BusinessCategoryId
join BusinessGroup bg on bg.BusinessGroupId = bc.BusinessGroupId
where
(@SpecificBusinessGroup is null or bg.BusinessGroupId = @SpecificBusinessGroup)
and (@SpecificBusinessCategory is null or bc.BusinessCategoryId = @SpecificBusinessCategory)
group by ebc.EntityId
) gr on gr.EntityId = SubmittedBy.PartyId
LEFT JOIN ...
WHERE
AND gr.EntityId IS NOT NULL -- Equivalent to EXISTS from the correlated subquery ???
答案 0 :(得分:0)
您可以尝试使用UNION
使用两个查询,然后您不需要使用GROUP BY
LEFT JOIN
(
select ebc.EntityId
from EntityBusinessCategoryMap ebc
left join BusinessCategory bc on bc.BusinessCategoryId = ebc.BusinessCategoryId
where
(@SpecificBusinessCategory is null or bc.BusinessCategoryId = @SpecificBusinessCategory)
UNION
select ebc.EntityId
from EntityBusinessCategoryMap ebc
left join BusinessGroup bg on bg.BusinessGroupId = ebc.BusinessGroupId
where
(@SpecificBusinessGroup is null or bg.BusinessGroupId = @SpecificBusinessGroup)
) gr on gr.EntityId = SubmittedBy.PartyId
答案 1 :(得分:0)
此:
如果变量作为null传入,则查询需要几秒钟 跑步。如果变量包含数据,则此查询需要一个多小时 跑。
表示您遇到了parameter sniffing问题。有几种方法可以绕过它,具体取决于您的SQL Server版本:
OPTIMIZE FOR UNKNOWN
查询提示,以便SQL Server构建更平均的执行计划。 Here是对它的简短描述。WITH RECOMPILE
(或查询中的OPTION(RECOMPILE)
),但我不推荐它 - 这不应该是除非所有警告都被理解,否则使用它,因为不断的重新编译会给你的系统带来很大的压力。答案 2 :(得分:0)
找到解决方案。几乎将 EXISTS 更改为 IN 。通过使用EXISTS,这会强制子查询相关,因为您使用子查询中的SubmittedBy.PartyId来引用子查询之外的表。通过使用IN,可以将其转换为非相关子查询。现在表现很好。
SELECT *
FROM
PremiumFinanceLoan pfl
LEFT JOIN CustomerAccount c ON pfl.CustomerAccountId = c.PartyId
LEFT JOIN Entity SubmittedBy ON c.SubmittedById = SubmittedBy.PartyId
LEFT JOIN ...
WHERE
(@SpecificBusinessGroup IS NULL OR @SpecificBusinessCategory IS NULL OR SubmittedBy.PartyId IN
(
select DISTINCT EBC.EntityId -- That way we will get one row for each group
from EntityBusinessCategoryMap as EBC
inner join BusinessCategory as BC on BC.BusinessCategoryId = EBC.BusinessCategoryId
inner join BusinessGroup as BG on BG.BusinessGroupId = BC.BusinessGroupId
where
(@SpecificBusinessGroup IS NULL OR BG.BusinessGroupId = @SpecificBusinessGroup)
AND (@SpecificBusinessCategory IS NULL OR BC.BusinessCategoryId = @SpecificBusinessCategory)
))