我有一个需要1:20分钟执行的sql。它处理一年的数据,但即便如此,我觉得它需要太长时间。我根据另一个查询的建议更改了IN使用EXISTS(在这种情况下,优化不是:S) 你还有其他的优化方法来优化吗?
select gd.descripcion,count(gd.descripcion) as total
from diagnosticos d,gruposdiagnosticos gd, ServiciosMedicos s, pacientes p,Actos a,historias h
where p.codigo=h.codpaciente and p.codigo=a.codpaciente and p.codigo=h.codpaciente and p.codigo=s.codpaciente and h.codpaciente=a.codpaciente and h.codpaciente=s.codpaciente and a.codpaciente=s.codpaciente and h.numhistoria=a.numhistoria and h.numhistoria=s.numhistoria and a.numacto=s.numacto and h.codseccion=a.codseccion and a.codseccion=s.codseccion and d.codigo=s.codDiagnostico and gd.codigo=d.codgrupo
and p.codcompañia ='35' and a.codseccion ='18'
and (CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >='20090101')
and (CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) <='20091231')
and h.modo ='Urgente'
and datename(weekday,a.fecatencion)!= 'Sabado'
and datename(weekday,a.fecatencion)!= 'Domingo'
AND NOT EXISTS (select * from diasfestivos af where (datename(d,a.fecatencion) + datename(m,a.fecatencion))=(datename(d,af.fechafestiva) + datename(m,af.fechafestiva)) AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >= af.fechafestiva AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) < af.fechafestiva + 1 and datepart(yy,af.fechafestiva)='1990')
AND NOT EXISTS (SELECT * FROM diasfestivos af WHERE CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >= af.fechafestiva AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) < af.fechafestiva + 1 AND datepart(yy,af.fechafestiva)!=1990)
group by gd.descripcion order by gd.descripcion
使用您的建议更改查询,使其在50秒内完成,谢谢,但应该有一种方法可以减少更多...现在的查询是:
select gd.descripcion,count(gd.descripcion) as total
from diagnosticos d,gruposdiagnosticos gd, ServiciosMedicos s, pacientes p,Actos a,historias h
where p.codigo=h.codpaciente and p.codigo=a.codpaciente and p.codigo=h.codpaciente and p.codigo=s.codpaciente and h.codpaciente=a.codpaciente and h.codpaciente=s.codpaciente and a.codpaciente=s.codpaciente and h.numhistoria=a.numhistoria and h.numhistoria=s.numhistoria and a.numacto=s.numacto and h.codseccion=a.codseccion and a.codseccion=s.codseccion and d.codigo=s.codDiagnostico and gd.codigo=d.codgrupo
and p.codcompañia ='35' and a.codseccion ='18'
and a.fecAtencion +1 >'20090101'
and a.fecAtencion -1 <'20091231'
and h.modo ='Urgente'
and DATEPART(dw,a.fecatencion)!=6
and DATEPART(dw,a.fecatencion)!=7
AND NOT EXISTS (select * from diasfestivos af where (datename(d,a.fecatencion) + datename(m,a.fecatencion))=(datename(d,af.fechafestiva) + datename(m,af.fechafestiva)) AND a.fecAtencion +1 > af.fechafestiva AND a.fecAtencion -1 < af.fechafestiva and datepart(yy,af.fechafestiva)='1990')
AND NOT EXISTS (SELECT * FROM diasfestivos af WHERE a.fecAtencion +1 > af.fechafestiva AND a.fecAtencion -1 < af.fechafestiva AND datepart(yy,af.fechafestiva)!=1990)
group by gd.descripcion order by gd.descripcion
我有两个存在的部分因为我有两种类型的节日日期。特别是今年和其他每年适用的人(所以我插入它们像25/12/1990)
最后我发现了这个问题..
其中datename(d,a.fecatencion)+ datename(m,a.fecatencion))=(datename(d,af.fechafestiva)+ datename(m,af.fechafestiva))
有人知道更好的方法吗? (比较tsql省略年份的2个日期时间)
答案 0 :(得分:6)
between ... and
语法datename(weekday,a.fecatencion)!= 'Sabado'
Actos a
表,并用h.codseccion = '18'替换a.codseccion ='18'diagnosticos d
表,因为我没有看到任何对它的引用ServiciosMedicos s
表,因为我没有看到任何对它的引用union all
例如:( select * from)table union all(select * from),那么至少你将有一次运行而不是两次答案 1 :(得分:1)
如果你必须做所有的演员和地板,那么你的数据库设计是需要的。我坚信数据应该以您需要查询的形式存储。考虑在插入/更新数据时添加列来执行此操作,您可以创建计算字段。然后,每次运行查询时都不必发生这种情况。
答案 2 :(得分:1)
这部分看起来可能是主要问题:
AND NOT EXISTS (
select * from diasfestivos af
where (datename(d,a.fecatencion) + datename(m,a.fecatencion))=
(datename(d,af.fechafestiva) + datename(m,af.fechafestiva))
AND a.fecAtencion +1 > af.fechafestiva
AND a.fecAtencion -1 < af.fechafestiva
and datepart(yy,af.fechafestiva)='1990'
)
这看起来基本上是:
AND NOT EXISTS (
SELECT NULL FROM diasfestivos af
WHERE af.fechafestiva BETWEEN '19900101' AND '19910101'
AND DATEPART(d, a.fecatencion) = DATEPART(d, af.fechafestiva)
AND DATEPART(m, a.fecatencion) = DATEPART(m, af.fechafestiva)
AND a.fecatencion != af.fechafestiva
)
我一直试图找到一种方法来做同一个日期,但不同的一年,而不必在日期执行多个功能,但我没有设法。
答案 3 :(得分:0)
同时尝试“Sql Server Profiler”。
考虑联接的顺序,以便首先过滤掉大块数据。
答案 4 :(得分:0)
您应该学习如何使用“DateDiff”。查询应使用此构造仅获取2009年的记录:
DATEDIFF(yy, a.fecAtencion, '2009-01-01')
其他一些事情......
首先 - 不要为日期做演员表。
静态日期(例如'2009-01-01')具有隐含的午夜(00:00:00)开始时间。因此,您在开始日期根本不需要演员表,因为2009年的所有内容都大于“2009-01-01”。您也可以使用“2010-01-01”作为结束日期,因为2009年之前(2010年没有任何内容)将在此之前完成。
不使用这些丑陋的强制转换的另一个原因是你可以在SQL查询中指定小时,分钟,秒和msecs,如下所示:'2009-01-01 00:00:00:000'如果你不想要在这个区域留下不明确的查询。
关于使用分析器等的其他建议仍然很好。但我敢打赌你的问题在于你的日期处理。
答案 5 :(得分:0)
以vb.net为例。
我的目标是移除将结果分组/计数到sql server的压力。
尝试这种额外的优化,看看它是否可以缩短执行时间?
strsql="
select gd.descripcion
from diagnosticos d,gruposdiagnosticos gd, ServiciosMedicos s, pacientes p,Actos a,historias h
where p.codigo=h.codpaciente and p.codigo=a.codpaciente and p.codigo=h.codpaciente and p.codigo=s.codpaciente and h.codpaciente=a.codpaciente and h.codpaciente=s.codpaciente and a.codpaciente=s.codpaciente and h.numhistoria=a.numhistoria and h.numhistoria=s.numhistoria and a.numacto=s.numacto and h.codseccion=a.codseccion and a.codseccion=s.codseccion and d.codigo=s.codDiagnostico and gd.codigo=d.codgrupo
and p.codcompañia ='35' and a.codseccion ='18'
and (CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >='20090101')
and (CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) <='20091231')
and h.modo ='Urgente'
and datename(weekday,a.fecatencion)!= 'Sabado'
and datename(weekday,a.fecatencion)!= 'Domingo'
AND NOT EXISTS (select * from diasfestivos af where (datename(d,a.fecatencion) + datename(m,a.fecatencion))=(datename(d,af.fechafestiva) + datename(m,af.fechafestiva)) AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >= af.fechafestiva AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) < af.fechafestiva + 1 and datepart(yy,af.fechafestiva)='1990')
AND NOT EXISTS (SELECT * FROM diasfestivos af WHERE CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) >= af.fechafestiva AND CAST(FLOOR(CAST(a.fecAtencion AS float)) AS datetime) < af.fechafestiva + 1 AND datepart(yy,af.fechafestiva)!=1990)
"
cmd = new sqlcommand(strsql, conn)
cmd.commandtimeout = 480
da = new sqldataadapter(cmd)
dt = new datatable
da.fill(dt)
dim dv as new dataview(dt)
dv.sort = "descripcion"
dt2 = dv.totable(true, "descripcion") 'simulate a select distinct from result
dt2.columns.add("total")
for each dr as datarow in dt2.rows
dr("total") = dt.select("descripcion = '" & dr("descripcion ") & "'").length
next
dt2.acceptchanges()
gridview2.datasource = dt2
gridview2.databind