最適化したいこのクエリがあります
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
変更できないものがいくつかあります。たとえば、xmlの代わりにIDを送信する(コードを変更する必要があり、変更できないため)、テーブルの構造などです。私はこれを変更することしかできません。このクエリはいくつかのIDを受け取り、一時テーブル(#Seleccionados
)に挿入し、それを使用していくつかの結合を実行し、売上などに関する情報を取得します。また、ハーコードされた値を持つユニオンALLなど、奇妙なものを見ることができます。これは、コード内のレポートが行われた方法であり、それを変更することもできないためです(つまり、その奇妙なことについて心配する必要はありません)。これは基本的に4つの選択を返します。そのうちの1つは1行だけなので、他の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を使用して、それを減らすことができると思います。where
しかし、そのselect、そのサブクエリは、サブクエリを使用するときのselectの値に依存します(そのサブクエリの句で私が言っていることを確認できます)
それから私は、しかし、3つの選択はそれほど違いはありません。いくつかの結合が繰り返されていますが、異なる方法でグループ化されています。ですから、私もある種の一時的なテーブルまたはCTEを使用することを考えていますが、それらは異なる方法でグループ化されており、1つまたは2つの異なるものがあるため、それについてはよくわかりません。JOINS
いくつかの追加情報:
#Seleccionados
100行のIDがあります。このクエリは50セグかかります。1週間:
- 最初のクエリは
47083 rows
- 2番目のクエリは
47084 rows
- 3番目のクエリは
47084 rows
ご覧のとおり、これはほぼ同じ情報であり、異なる方法でグループ化されています。
表:
Fact_Comprobante
1つの販売に関する情報を取得しました。Fact_ComprobanteItem
セール品について。
Dim_Producto
1つの製品に関するDim_Familia
情報、製品のファミリに関する情報、Dim_Marca
製品のサインに関する情報、Dim_Linea
製品のラインに関する情報を取得しました(これらの3つのテーブルはDim_ProductoのFKです)。
Dim_ComprobanteTipo
販売の種類に関する情報を
Fact_Descuento
取得しました。販売に関連する割引に関する情報を取得しました。
すべてのテーブルに多くの情報がありました。
これらの(Nolock)
テーブルには、3つのサービスが同時に挿入、更新、その他のものがあるためです。
私はこのクエリを実行しませんでした。最適化する必要があります。