Ingreso auto en datos variables
-
12-09-2019 - |
Pregunta
Tengo una tabla con los siguientes datos:
Fiscal Year | Fiscal Quarter | Fiscal Week | Data
2009 | 2 | 22 | 9.5
2009 | 2 | 24 | 8.8
2009 | 2 | 26 | 8.8
2009 | 3 | 28 | 8.8
2009 | 3 | 31 | 9.1
2009 | 3 | 33 | 8.8
Me gustaría escribir una consulta que produciría el siguiente:
Fiscal Year | Fiscal Quarter | Fiscal Week | Data | Trend
2009 | 2 | 22 | 9.5 | NULL
2009 | 2 | 24 | 8.8 | -0.7
2009 | 2 | 26 | 8.8 | 0
2009 | 3 | 28 | 8.8 | 0
2009 | 3 | 31 | 9.1 | 0.3
2009 | 3 | 33 | 8.8 | -0.3
Sé que esto puede lograrse fácilmente haciendo una simple unión de las tablas a sí mismo con la semana fiscal anterior, sin embargo, esto no siempre será un t1.[Fiscal Week] = t2.[Fiscal Week] - 2
sencilla porque a veces la diferencia es de 3 semanas.
Puedo tirar del registro máximo fácilmente con algo como esto:
SELECT
MAX(t1.[Fiscal Week]) "LastWeek"
FROM t1
WHERE t1.[Fiscal Year] = 2009
AND t1.[Fiscal Week] < 31
Pero estoy en una pérdida cuando se trata de la abstracción para hacer el trabajo unirse.
¿Cómo puedo hacer una auto unirse en "el más grande semanas fiscal que es más pequeño que el registro actual"?
Solución
La manera más fácil de hacer esto con SQL 2005 + es utilizar la funciones de ventanas - simplemente partición / ordenar sus datos y asignar una secuencia apropiada para cada registro (en este caso está particionando por fiscalYear y pedidos por fiscalWeek sobre esa ventana) - sería algo como esto:
with data as
(
select row_number() over (partition by a.fiscalYear order by a.fiscalWeek) as rn,
a.fiscalYear, a.fiscalQuarter, a.fiscalWeek, a.Data
from #TableName a
)
select a.fiscalYear, a.fiscalQuarter, a.fiscalWeek, a.Data,
a.Data - b.Data as Trend
from data a
left join data b
on a.fiscalYear = b.fiscalYear
and a.rn = b.rn + 1
order by a.fiscalYear, a.rn
Esta consulta en particular no permitiría la extensión a través de fronteras fiscalYear - si desea extender a cruzar estas fronteras año sólo tendría que quieren dejar caer la "partición" cláusula y "fiscalYear" condición de combinación y en lugar de ordenar el establecido por una combinación del fiscalYear y fiscalWeek, algo como esto:
with data as
(
select row_number() over (order by a.fiscalYear + a.fiscalWeek) as rn,
a.fiscalYear, a.fiscalQuarter, a.fiscalWeek, a.Data
from #TableName a
)
select a.fiscalYear, a.fiscalQuarter, a.fiscalWeek, a.Data,
a.Data - b.Data as Trend
from data a
left join data b
on a.rn = b.rn + 1
order by a.rn
Otros consejos
Cómo funciona? La consulta en línea es un poco de un bocado y es probable que haya una mejor manera de hacerlo ...
select
[fiscal year]
, [fiscal quarter]
, [fiscal week]
, [data]
, (
select top 1 (i.data - t1.data) from t1 as i
where i.[fiscal year] >= t1.[fiscal year]
and i.[fiscal quarter] >= t1.[fiscal quarter]
and i.[fiscal week] >= t1.[fiscal week]
and (
i.[fiscal year] <> t1.[fiscal year]
or i.[fiscal quarter] <> t1.[fiscal quarter]
or i.[fiscal week] <> t1.[fiscal week]
)
order by [fiscal year] asc, [fiscal quarter] asc, [fiscal week] asc
) as trend
from t1
Si está utilizando SQL Server 2005, puede utilizar la cláusula CROSS APPLY
.
Aquí podría tener una función con valores de tabla, que devolverá la fila para la semana fiscal, antes de la una en la fila actual.
CREATE FUNCTION dbo.fn_GetFiscalWeekBeforeThis(@Year AS int,
@CurrentWeek as int)
RETURNS TABLE
AS
RETURN
SELECT TOP 1 *
FROM t1
WHERE [Fiscal Year] = @Year
AND [Fiscal Week] < @CurrentWeek
ORDER BY [Fiscal Week] DESC
GO
Y a continuación,
SELECT A.*,
A.Data - B.Data
FROM
t1 A
CROSS APPLY
dbo.fn_GetFiscalWeekBeforeThis(A.[Fiscal Year],
A.[Fiscal Week]) AS B
EDIT: Tenga en cuenta que he adaptado el SQL examinado un artículo y sin un IDE
.
Además, no sé -. Cómo se va a trabajar para la primera fila
Así que, por favor, ser amable:)
Edit2: Quiero saber, si no funciona en absoluto
.
Esto me ayudará a conocer -. No responder a las cosas, sin comprobar los resultados
Edit3:. I Se ha eliminado la necesidad de parámetro cuartos de la función
DECLARE @Fiscal TABLE
(
FiscalYear int
,FiscalQuarter int
,FiscalWeek int
,[Data] decimal(4,1)
)
INSERT INTO @Fiscal
( FiscalYear, FiscalQuarter, FiscalWeek, [Data] )
SELECT 2009, 2, 22, 9.5 UNION
SELECT 2009, 2, 24, 8.8 UNION
SELECT 2009, 2, 26, 8.8 UNION
SELECT 2009, 3, 28, 8.8 UNION
SELECT 2009, 3, 31, 9.1 UNION
SELECT 2009, 3, 33, 8.8 UNION
SELECT 2010, 1, 1, 9.0 UNION
SELECT 2010, 1, 2, 9.2
;
WITH abcd
AS ( SELECT FiscalYear
,FiscalQuarter
,FiscalWeek
,[Data]
,row_number() OVER ( ORDER BY FiscalYear, FiscalWeek ) AS rn
FROM @Fiscal
)
SELECT a.FiscalYear
,a.FiscalQuarter
,a.FiscalWeek
,a.[Data]
,a.[Data] - b.[Data] AS [Trend]
FROM abcd AS a
LEFT JOIN abcd AS b ON b.rn = ( a.rn - 1 )
ORDER BY a.FiscalYear
,a.FiscalWeek