Joh*_*ohn 6 t-sql sql-server-2008
假设我有一个存储过程,它会在参数时执行复杂的逻辑@ComplicatedSearch = 1.当它设置为1时,我@ValidIds使用此过程可以返回的有效行填充变量表.当它为0时,逻辑被绕过,我们不需要过滤掉要返回的行.
所以,通过这个逻辑,我最终会得到如下声明:
SELECT
m.*
,a.*
FROM
MyTable m
INNER JOIN AdditionalInfoTable a
ON m.Id = a.MyTableId
WHERE
(@ComplicatedSearch = 0 OR EXISTS(SELECT * FROM @ValidIds WHERE Id = m.Id))
Run Code Online (Sandbox Code Playgroud)
这很好用; 但是,我认为将MyTable加入@ValidIds会更有效,适用时反对使用EXISTS(),特别是当MyTable包含大量行时.
有没有办法在不编写多个查询的情况下执行下面的操作?(实际的查询非常大,因此有多个版本的连接和不连接都不是理想的)
SELECT
m.*
,a.*
FROM
MyTable m
ONLY DO THIS IF ComplicatedSearch = 1 PLEASE: INNER JOIN @ValidIds v
ON m.Id = v.Id
INNER JOIN AdditionalInfoTable a
ON m.Id = a.MyTableId
Run Code Online (Sandbox Code Playgroud)
另外一个选项:
SELECT
m.*
,a.*
FROM MyTable m
INNER JOIN @ValidIds v
ON m.Id = case
when @ComplicatedSearch = 1 then v.Id -- Filter rows
else m.Id -- Select all rows
end
INNER JOIN AdditionalInfoTable a
ON m.Id = a.MyTableId
Run Code Online (Sandbox Code Playgroud)
您需要进行性能测试,看看它是否足够高效.一些快速测试显示(在我的数据上)生成相同的查询计划,无论第一次调用是复杂还是非复杂.
"分叉"方法(单独的程序)应该是最有效的.但是,在两个不同的地方只需稍作修改即可获得相同的代码,这可能是一个很大的难点,特别是当您必须向该代码的所有"实例"添加后续更改时.如果数据的总体大小(例如整体性能)不是太大,那么"一种尺寸最适合所有"的方法可能是最有效的.
如果您追求效率,则应注意存储过程将在第一次运行时计算查询计划,然后对其进行缓存并在此后使用相同的查询计划.在这种情况下,它意味着它将根据@ComplicatedSearch的第一个值选择使用@ValidIds
因此,我会更喜欢编写程序
if @ComplicatedSearch = 1
exec simple_search
else
exec complex_search
Run Code Online (Sandbox Code Playgroud)
其中simple_search包含您的第一个查询,complex_search也加入@ValidIds
你是否得到了两次查询,但为了克服这个问题,我会创建一个视图
create view helper as
begin
SELECT
m.*
,a.*
FROM
MyTable m
INNER JOIN AdditionalInfoTable a
ON m.Id = a.MyTableId
end
Run Code Online (Sandbox Code Playgroud)
然后从该视图和复杂连接中简单选择@ValidIds
| 归档时间: |
|
| 查看次数: |
3474 次 |
| 最近记录: |