在此查询的code_list
CTE中,我有一个行构造函数,最终将获取任意数量的参数。 icd
CTE中的列patient_codes
是一个五位数的标识符,最能描述行构造函数具有的三位数代码。表icd_patient
有1亿行,所以为了性能,我想在进行任何进一步的工作之前在这个表上记录行。我有
;with code_list(code_list)
as
(
select x.code_list
from (values ('70700'),('25002')) as x(code_list)
),patient_codes
as
(
select distinct icd,pat_id,id
from icd_patient
where icd in (select icd from code_list)
)
select distinct pat_id from patient_codes
但问题是,在icd_patient表中,所有icd
列都是五位数且更具描述性。如果我查看此查询的执行计划,它会非常精简。如果我做
;with code_list(code_list)
as
(
select x.code_list
from (values ('70700'),('25002')) as x(code_list)
),patient_codes
as
(
select substring(icd,1,3) as icd,pat_id
from icd_patient2
where substring(icd,1,3) in (select * from code_list)
)
select * from patient_codes
如果由于where子句中的子字符串表达式,课程会对性能产生很大影响。是否存在类似于like in
的内容,以便我可以利用我的索引?
icd_patient上的索引
CREATE NONCLUSTERED INDEX [ix_icd_patient] ON [dbo].[icd_patient2]
(
[pat_id] ASC
)
INCLUDE ( [id],
答案 0 :(得分:5)
这个更简单的查询应该比现有查询更好(或者,最坏,相同)。
select pat_id
FROM dbo.icd_patient
where icd LIKE '707%'
OR icd LIKE '250%'
GROUP BY pat_id;
请注意,只有在此列上实际存在索引时,sargability才会很重要。
另一种选择(因为OR
有时可以使优化器适合):
SELECT pat_id FROM
(
SELECT pat_id
FROM dbo.icd_patient
WHERE icd LIKE '707%'
UNION ALL
SELECT pat_id
FROM dbo.icd_patient
WHERE icd LIKE '250%'
) AS x
GROUP BY pat_id;
为了使这个可扩展性超出少数OR条件,我会使用表值参数(TVP)。
CREATE TYPE dbo.StringPatterns AS TABLE(s VARCHAR(3) PRIMARY KEY);
然后您的存储过程可以说:
CREATE PROCEDURE dbo.whatever
@sp dbo.StringPatterns READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT p.pat_id
FROM dbo.icd_patient AS p
INNER JOIN @sp AS sp
ON p.pat_id LIKE sp.s + '%'
GROUP BY p.pat_id;
END
然后,您可以从DataTable
或C#中的其他集合传入一组三字符子串。以T-SQL为例:
DECLARE @p dbo.StringPatterns;
INSERT @p VALUES('707'),('250');
EXEC dbo.whatever @sp = @p;
答案 1 :(得分:2)
like in
之类的东西不存在。以下是可以理解的:
select *
from icd_patient
where icd like '70700%' or
icd like '25002%'
因为具有常量初始子字符串的like
是SQL Server的特例。当右边的字符串是变量时,这不起作用。
一种解决方案是在icd_patient
表上创建一个索引视图,其中包含icd代码前五个字符的索引。
答案 2 :(得分:2)
使用“IN”使得两侧的命令部分都不可搜索。讨论结束。
说他使用子字符串修复它,完全改变它返回的内容,而它仍然没有被攻击。
任何“修复”都应与结果完全匹配。实际修复是加入cte所以五个字符匹配或在cte中放入三个字符并在连接中匹配或在cte中放入4个字符,其中第四个是“%”并使用LIKE连接匹配
使用以“%”开头的“like”会增加搜索的复杂性,但它仍然会使用索引来查找值,因为解析索引应该使用较少的读数,只需在搜索时获取完整的表行是成功的。