如何优化此查询(或内部 AND 验证)?
Posted
技术标签:
【中文标题】如何优化此查询(或内部 AND 验证)?【英文标题】:How Can I optimize this query (OR inside AND validation)? 【发布时间】:2011-11-29 19:25:20 【问题描述】:我遇到了这个查询的问题:
SELECT col1, col2,col3,...,coln FROM MyTable
WHERE col1 = @value1
AND
(
ISNULL(col2,'c') = ISNULL(@value2,ISNULL(col2,'c'))
OR
ISNULL(col3,'c') = ISNULL(@value2,ISNULL(col3,'c'))
)
AND coln = 'valueN'
我必须停止执行,太慢了。但编辑:
SELECT col1, col2,col3,...,coln FROM MyTable
WHERE col1 = @value1
AND
(
ISNULL(col2,'c') = ISNULL(@value2,ISNULL(col2,'c'))
)
AND coln = 'valueN'
这个查询速度更快。有人能帮我吗?如何替换 or 语句或替换查询但验证 col1 和 col2?。 谢谢。
更新:
非常感谢你们。真的,我的查询不使用'=',而是使用'Like',对此感到抱歉。但是,我使用您的建议来构建我的查询并且效果很好:
SELECT col1, col2,col3,...,coln FROM MyTable
WHERE col1 like '%' + @value1 + '%'
AND
(
(@value2 IS NULL)
OR
(col2 IS NOT NULL AND col2 LIKE '%' + @value2 + '%')
OR
(col3 IS NOT NULL AND col3 LIKE '%' + @value2 + '%')
)
AND coln = 'valueN'
我将此查询与一个页面一起使用,其中我有许多字段来过滤搜索,并且我需要一个 col2 文本框也适用于数据库中的 col3,我的意思是,数据库中只有一个用于 name1 和 name2 的文本框。
对不起,我的错误问题,感谢您的建议。
【问题讨论】:
您能否根据 value2 是否为空来更改参数化查询?坏情况的查询计划有什么明显的地方吗? 感谢您的回答。 Adrian 解决方案工作正常,查询必须验证必要的,而不是像我总是验证的旧查询。 【参考方案1】:ISNULL(col2,'c') = ISNULL('value2',ISNULL(col2,'c'))
和
一样col2 = 'value2' or (col2 is null and 'value2' is null)
替换出现的次数,您很可能会获得更好的性能。
更新
此解决方案与@onedaywhen 提出的解决方案有一个根本区别:当'value2'
中提供的值(我想这只是一个组装成SQL 字符串的参数)是NULL
时,OP 只想带仅返回 col2 为 NULL 的记录。仔细看看 OP 的逻辑,你会在那里看到。 OP的逻辑总是过滤:当参数为NULL
时,OP想要col2 is NULL
的记录。
@onedaywhen 的解决方案在参数为NULL
时带来every 记录。虽然这是一个非常常见的查询,但这不是 OP 正在寻找的。
【讨论】:
工作正常!!。非常感谢。 您的断言(“相同”)是错误的。考虑ISNULL('value2',ISNULL(col2,'c'))
将始终评估为“value2”。
...即使您将'value2'
更正为@value2
,您的建议也不等同于OP!
@onedaywhen 我同意value2
应该是@value2
。也就是说,仔细查看 OP 的逻辑,您会看到 OP 的要求:查询将始终过滤!如果参数为 NULL,OP 只想带 col2 为 NULL 的记录,不是每条记录。
你同意如果列和参数值都为空,那么ISNULL
逻辑会认为它们都是c
吗?这有效地改变了 SQL 的 3VL 逻辑,以便NULL = NULL
为该谓词计算 TRUE。请参阅我的更新答案以进行演示:)【参考方案2】:
ISNULL(col2,'c') = ISNULL(@value2,ISNULL(col2,'c'))
和
一样( ( col2 = @value2 ) OR ( @value2 IS NULL ) )
但我不确定这是否会提高性能:我已经阅读过 to get an efficient, scalable and performant solution either use IF ELSE
control of flow blocks (one per parameter combination) or use dynamic SQL,至少对于 SQL Server 2005 及更早版本。
更新:...这是证据:
查询一:当参数为非空值时:
DECLARE @value2 VARCHAR(10);
SET @value2 = 'Apples';
WITH T
AS
(
SELECT *
FROM (
VALUES (1, 'When col2 is null', NULL),
(2, 'When col2 is the same value as @value2', 'Apples'),
(3, 'When col2 is not the same value as @value2', 'Oranges')
) AS T (ID, narrative, col2)
)
SELECT *,
CASE WHEN ISNULL(col2,'c') = ISNULL(@value2,ISNULL(col2,'c')) THEN 'T' END AS OP,
CASE WHEN ( ( col2 = @value2 ) OR ( @value2 IS NULL ) ) THEN 'T' END AS OneDayWhen,
CASE WHEN col2 = @value2 or (col2 is null and @value2 is null) THEN 'T' END AS Adrian
FROM T;
输出 1:
ID narrative col2 OP OneDayWhen Adrian
----------- ------------------------------------------ ------- ---- ---------- ------
1 When col2 is null NULL NULL NULL NULL
2 When col2 is the same value as @value2 Apples T T T
3 When col2 is not the same value as @value2 Oranges NULL NULL NULL
注意所有行都同意:)
查询2:当参数为空时:
DECLARE @value2 VARCHAR(10);
SET @value2 = NULL;
WITH T
AS
(
SELECT *
FROM (
VALUES (1, 'When col2 is null', NULL),
(2, 'When col2 is the same value as @value2', 'Apples'),
(3, 'When col2 is not the same value as @value2', 'Oranges')
) AS T (ID, narrative, col2)
)
SELECT *,
CASE WHEN ISNULL(col2,'c') = ISNULL(@value2,ISNULL(col2,'c')) THEN 'T' END AS OP,
CASE WHEN ( ( col2 = @value2 ) OR ( @value2 IS NULL ) ) THEN 'T' END AS OneDayWhen,
CASE WHEN col2 = @value2 or (col2 is null and @value2 is null) THEN 'T' END AS Adrian
FROM T;
输出 2:
ID narrative col2 OP OneDayWhen Adrian
----------- ------------------------------------------ ------- ---- ---------- ------
1 When col2 is null NULL T T T
2 When col2 is the same value as @value2 Apples T T NULL
3 When col2 is not the same value as @value2 Oranges T T NULL
注意 OP 和 OneDayWhen 匹配所有行,Adrian 仅匹配行 ID = 1。
【讨论】:
你是对的。但我敢打赌,OP 想要 Adrian 的逻辑。 @ypercube:我会接受这个赌注;) @ypercube 请花点时间阅读我的答案更新。谢谢以上是关于如何优化此查询(或内部 AND 验证)?的主要内容,如果未能解决你的问题,请参考以下文章