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"?

Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top