我有这个想要优化的查询
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ComprobantesFacturasObtenerEstadisticasLocal2]
(
@FechaDesde DateTime,
@FechaHasta DateTime,
@XML ntext
)
AS
BEGIN
DECLARE @docHandler INT
EXEC sp_xml_preparedocument @docHandler OUTPUT, @XML
--Locales
Select IdLocal
into #seleccionados
FROM OPENXML(@docHandler, N'/NewDataSet/Table1', 2)
WITH (IdLocal int)
select d.* into #Locales from Dim_Sucursal d inner join GrimRepCen..Locales l on l.Codigo = d.Codigo inner join #seleccionados s on s.IdLocal = l.iDlocal
/*2011/12/06 busco los descuentos del rio*/
select distinct l.Codigo + ' - ' + l.Nombre as local, c.IdComprobante, -1 as Cantidad,
-1 * isnull(abs(c.TotalNeto),0) as IMPORTE,
'Varios' as Familia, 'Dto Bco Rio' as Linea
into #descuentoRio
from Fact_Comprobante(nolock) c
--inner join Fact_ComprobanteItem(nolock) ci on ci.IdComprobante = c.IdComprobante
inner join #locales l on c.idDim_ComprobanteTipo = 5 and l.IdDim_sucursal = c.IdDim_sucursal and c.fecha between @FechaDesde and @FechaHasta
/*******************COMPROBANTES************************************************ */
select distinct
c.*, l.Codigo + ' - ' + l.Nombre as local, ct.IdComprobanteTipo
into #Comprobantes
from Fact_Comprobante(nolock) c
inner join Fact_ComprobanteItem(nolock) ci on ci.IdCOmprobante = c.IdComprobante
inner join Dim_ComprobanteTipo(nolock) ct on ct.IdDim_ComprobanteTipo = c.idDim_ComprobanteTipo
inner join #locales l on l.IdDim_sucursal = c.IdDim_sucursal and ct.IdComprobanteTipo not in (46 /*Error Fiscal Factura B*/, 47 /*Error Fiscal Factura A*/) and c.fecha between @FechaDesde and @FechaHasta
--Comprobantes por Linea/Marca/Familia
select
m.Nombre as Marca, l.Nombre as Linea , case when c.IdComprobanteTipo in (21,23,26,28) then 0 else -sum(ci.Cantidad) end as Cantidad,
case when c.IdComprobanteTipo in (21,23,26,28)
--toma en cuenta los descuentos de las facturas que fueron anuladas
then c.TotalNeto
else isnull(ci.ImporteNeto,0) - isnull((select sum(importe) as importe
from Fact_Descuento (nolock) DD
where DD.IdComprobante = ci.idComprobante and ci.IdDim_Producto = IdDim_Producto
and ci.IdDim_Medida = IdDim_Medida and ci.IdDim_Calidad = IdDim_Calidad
and exists
(
select 1
from ComprobanteReferencias AA
inner join Fact_Comprobante BB on aa.IdComprobanteCredito = BB.IdComprobante
where AA.IdComprobanteDebito = DD.IdComprobante
and BB.IdDim_ComprobanteTipo in (4,13,16,19)
)
),0)
end as IMPORTE,
f.Nombre as Familia
from #Comprobantes c
inner join Fact_ComprobanteItem(nolock) ci on ci.IdComprobante = c.IdComprobante
inner join Dim_Producto(nolock) p on p.IdDim_Producto = ci.IdDim_Producto
inner join Dim_Marca(nolock) m on m.IdDim_Marca = p.IDDim_Marca
inner join Dim_Familia(nolock) f on f.idDim_Familia = p.IdDim_Familia
inner join Dim_Linea(nolock) l on l.IdDim_Linea = p.IdDim_Linea
Group by m.Nombre,l.Nombre,f.Nombre,c.TotalNeto,ci.IdComprobante, ci.IdDim_producto,
ci.idDim_Medida,ci.ImporteNeto,c.IdComprobanteTipo ,ci.IdDim_Calidad
union all
select 'Grimoldi' as Marca, Linea , - 1 Cantidad,
IMPORTE,
Familia
from #descuentoRio
--/*Familia*/
select case when c.IdComprobanteTipo in (21,23,26,28) then 0 else -isnull(sum(ci.Cantidad),0) end as Cantidad,
case when c.IdComprobanteTipo in (21,23,26,28)
--toma en cuenta los descuentos de las facturas que fueron anuladas
then c.TotalNeto
else isnull(ci.ImporteNeto,0) - isnull((select sum(importe) as importe
from Fact_Descuento (nolock) DD
where DD.IdComprobante = ci.idComprobante and ci.IdDim_Producto = IdDim_Producto
and ci.IdDim_Medida = IdDim_Medida and ci.IdDim_Calidad = IdDim_Calidad
and exists
(
select 1
from ComprobanteReferencias AA
inner join Fact_Comprobante BB on aa.IdComprobanteCredito = BB.IdComprobante
where AA.IdComprobanteDebito = DD.IdComprobante
and BB.IdDim_ComprobanteTipo in (4,13,16,19)
)
),0)
end as IMPORTE,
f.Nombre as Familia
from #Comprobantes c
inner join Comprobantes(nolock) co on co.IdComprobante = c.IdComprobante
inner join Fact_ComprobanteItem(nolock) ci on ci.IdComprobante = c.IdComprobante
inner join Dim_Producto(nolock) p on p.IdDim_Producto = ci.IdDim_Producto
full outer join Dim_Familia(nolock) f on f.idDim_Familia = p.IdDim_Familia
Group by f.Nombre,ci.ImporteNeto,ci.IdComprobante, ci.IdDim_producto,
ci.idDim_Medida,c.TotalNeto, c.IdComprobanteTipo ,ci.IdDim_Calidad
union all
select -1 as Cantidad,
IMPORTE,
Familia
from #descuentoRio
/*local*/
select c.Local, case when c.IdComprobanteTipo in (21,23,26,28) then 0 else -isnull((sum(ci.Cantidad)),0) end as Cantidad,
case when c.IdComprobanteTipo in (21,23,26,28)
--toma en cuenta los descuentos de las facturas que fueron anuladas
then c.TotalNeto
else isnull(ci.ImporteNeto,0) - isnull((select sum(importe) as importe
from Fact_Descuento (nolock) DD
where DD.IdComprobante = ci.idComprobante and ci.IdDim_Producto = IdDim_Producto
and ci.IdDim_Medida = IdDim_Medida and ci.IdDim_Calidad = IdDim_Calidad
and exists
(
select 1
from ComprobanteReferencias AA
inner join Fact_Comprobante BB on aa.IdComprobanteCredito = BB.IdComprobante
where AA.IdComprobanteDebito = DD.IdComprobante
and BB.IdDim_ComprobanteTipo in (4,13,16,19)
)
),0)
end as IMPORTE,
f.Nombre as Familia, l.Nombre as Linea
from #Comprobantes c
inner join Comprobantes(nolock) co on co.IdComprobante = c.IdComprobante
inner join Fact_ComprobanteItem(nolock) ci on ci.IdComprobante = c.IdComprobante
inner join Dim_Producto(nolock) p on p.IdDim_Producto = ci.IdDim_Producto
inner join Dim_Linea(nolock) l on l.IdDim_Linea = p.IdDim_Linea
inner join Dim_Familia(nolock) f on f.idDim_Familia = p.IdDim_Familia
Group by f.Nombre,ci.ImporteNeto, l.Nombre ,ci.IdComprobante, ci.IdDim_producto,
ci.idDim_Medida, c.Local,c.TotalNeto, c.IdComprobanteTipo,ci.IdDim_Calidad
union all
select Local, -1 as Cantidad,
IMPORTE,
Familia, Linea
from #descuentoRio
end
有一些我无法改变的事情,例如,以其他方式发送id而不是xml(因为我必须修改代码而我不能),表格的结构和其他东西。我只能修改这个存储的。
此查询接收一些Id,插入时态表(#Seleccionados
)并使用它来执行一些连接以获取有关销售和其他的信息。
此外,你可以看到奇怪的东西,作为具有编码价值的联盟ALL,以及其他东西。这是因为代码中的报告完成的方式,也无法改变(我的意思是,不要担心那些奇怪的事情)。
这个存储基本上返回4个选择:其中一个只是一行,所以我遇到了其他3个问题,我在这里向你展示。
我尝试了什么:
我在想的是尝试解决一些重复的事情,例如,这个子查询:
(select sum(importe) as importe
from Fact_Descuento (nolock) DD
where DD.IdComprobante = ci.idComprobante and ci.IdDim_Producto = IdDim_Producto
and ci.IdDim_Medida = IdDim_Medida and ci.IdDim_Calidad = IdDim_Calidad
and exists
(
select 1
from ComprobanteReferencias AA
inner join Fact_Comprobante BB on aa.IdComprobanteCredito = BB.IdComprobante
where AA.IdComprobanteDebito = DD.IdComprobante
and BB.IdDim_ComprobanteTipo in (4,13,16,19)
)
)
ISNULL
条款中的重复3次选择。所以,我认为我可以使用WITH Common_Expresion_Table并减少它。但是,那个select,它的子查询,所以取决于我使用子查询时select的值(可以看到我在该子查询的where
子句中所说的内容)
然后我,3选择没有那么不同。他们有几个连接重复,但按不同的方式分组。所以,我也想使用某种Temporally Table或CTE,但我不确定,因为它们是以不同的方式分组的,并且还有一两个不同的JOINS
一些额外信息:
#Seleccionados
将有100行Id。
此查询需要50个segs。一个星期:
47083 rows
47084 rows
47084 rows
正如您所看到的,它几乎是相同的信息,以不同的方式分组。
表:
Fact_Comprobante
获得了有关一次促销的信息。 Fact_ComprobanteItem
关于销售项目。
Dim_Producto
获取了有关产品系列的一个产品的信息Dim_Familia
,Dim_Marca
获得了有关产品标志的信息,Dim_Linea
获得了有关产品系列的信息(这3个表格)是Fim in Dim_Producto)。
Dim_ComprobanteTipo
获得了有关销售类型的信息
Fact_Descuento
获得了与销售相关的折扣信息。
所有表格都有很多信息。
(Nolock)
语句是因为我们在这些表中同时有3个服务插入,更新和其他内容。
我没有做这个查询,我只需要优化它。
答案 0 :(得分:0)
使用SQL事件探查器(如果您有权访问它)并筛选存储过程的名称。确保显示每个步骤(因此运行该过程会产生超过1或2行)。然后在每一步中你都会看到nr of seconds,nr的读取,写入等等。那么你就可以专注于耗时的部分。
备选方案您可以使用此SQL分析备选方案:
declare @dStart datetime
set @dStart = getdate()
-- at every place you like to monitor
print 'a: ' + convert(nvarchar(datediff(ms, @dStart, getdate()))
如果没有深入到程序中,我将从子查询开始 并存在 ( ......
这可能是一个昂贵的,而是重写为左或右连接