Auto Junte-se em dados variável
-
12-09-2019 - |
Pergunta
Eu tenho uma tabela com os seguintes dados:
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
Eu gostaria de escrever uma consulta que deve produzir a seguinte:
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
Eu sei que isto pode ser facilmente alcançado, fazendo uma junção simples da tabela para si com a semana fiscal anterior, no entanto, este não será sempre uma t1.[Fiscal Week] = t2.[Fiscal Week] - 2
simples, porque às vezes a diferença é de 3 semanas.
Eu posso puxar o registro máximo facilmente com algo como isto:
SELECT
MAX(t1.[Fiscal Week]) "LastWeek"
FROM t1
WHERE t1.[Fiscal Year] = 2009
AND t1.[Fiscal Week] < 31
Mas eu estou em uma perda quando se trata de abstrair-lo para fazer o trabalho se juntar.
Como posso fazer uma auto juntar-se sobre "o maior semana fiscal que é menor do que o recorde atual"?
Solução
A maneira mais fácil de fazer isso com o SQL 2005 + é usar a ranking e funções de janelas - simplesmente partição / encomendar seus dados e atribuir uma seqüência apropriada para cada registro (neste caso, você está dividindo por fiscalYear e ordenação por fiscalWeek sobre essa janela) - seria algo parecido com isto:
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 específica não permitiria extensão para além das fronteiras fiscalYear - se você queria estender a cruzar essas fronteiras ano você simplesmente quer deixar cair a "partição" cláusula e "fiscalYear" condição de junção e, em vez encomendar o conjunto por uma combinação do fiscalYear e fiscalWeek, algo como isto:
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
Outras dicas
faz este trabalho? A consulta em linha é um pouco de um bocado e provavelmente há uma maneira melhor de fazê-lo ...
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
Se você estiver usando SQL Server 2005, você pode usar cláusula CROSS APPLY
.
Aqui você pode ter uma função com valor de tabela, que irá retornar a linha para a semana fiscal, antes da uma na linha atual.
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
E, em seguida,
SELECT A.*,
A.Data - B.Data
FROM
t1 A
CROSS APPLY
dbo.fn_GetFiscalWeekBeforeThis(A.[Fiscal Year],
A.[Fiscal Week]) AS B
EDIT: Note que eu adaptei o SQL, olhando para um artigo e sem um IDE
.
Além disso, eu não sei. - Como ele vai trabalhar para a primeira linha
Então, por favor, ser gentil:)
EDIT2: Deixe-me saber, se ele não funciona em todos
.
Isso vai me ajudar a conhecer -. Não responder coisas, sem verificar os resultados
EDIT3:. Eu removi a necessidade de parâmetro Bairro da função
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