Domanda

Ho una tabella con i seguenti dati:

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

Vorrei scrivere una query che produrrebbe il seguente:

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 

So che questo può essere facilmente raggiunto facendo una semplice join della tabella a se stesso con la settimana fiscale precedente, tuttavia questo non sarà sempre un semplice t1.[Fiscal Week] = t2.[Fiscal Week] - 2 perché a volte la differenza è di 3 settimane.

posso tirare il record massimo facilmente con qualcosa di simile:

SELECT
    MAX(t1.[Fiscal Week]) "LastWeek"
FROM t1
WHERE t1.[Fiscal Year] = 2009
    AND t1.[Fiscal Week] < 31

Ma io sono in perdita quando si tratta di astrazione per rendere il lavoro unirsi.

Come posso fare un self join su "la più grande settimana fiscale che è più piccola del record corrente"?

È stato utile?

Soluzione

Il modo più semplice per fare questo con Sql 2005+ è quello di utilizzare la classifica e funzioni di windowing - semplicemente partizione / ordinare i dati e assegnare una sequenza appropriata per ogni record (in questo caso si sta partizionamento fiscalYear e l'ordinazione da fiscalWeek oltre quella finestra) - sarebbe simile a questa:

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

Questa query particolare non avrebbe permesso l'estensione oltre i confini fiscalYear - se si voleva estendere ad attraversare questi confini anno si dovrebbe semplicemente vuole far cadere la "partizione" clausola e "fiscalYear" condizione di join e invece ordinare il set da una combinazione del fiscalYear e fiscalWeek, qualcosa di simile a questo:

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

Altri suggerimenti

funziona? La query in linea è un po 'di un boccone e c'è probabilmente un modo migliore di farlo ...

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 si utilizza SQL Server 2005, è possibile utilizzare la clausola CROSS APPLY.

Qui si potrebbe avere una tabella di funzione a valori, che restituirà la riga per la settimana fiscale, precedente a quello in riga corrente.

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 poi,

SELECT A.*,
A.Data - B.Data
FROM
t1 A
CROSS APPLY 
   dbo.fn_GetFiscalWeekBeforeThis(A.[Fiscal Year],  
   A.[Fiscal Week]) AS B

EDIT: Si noti che ho adattato il codice SQL, cercando in un articolo e senza un IDE
. Inoltre, non so -. Come funzionerà per la prima riga

Quindi, si prega di essere gentile:)

EDIT2: Fatemi sapere, se non funziona in tutte le nazioni. Questo mi aiuterà a conoscere -. Non rispondere le cose, senza controllare i risultati

Edit3:. Ho rimosso la necessità di parametri trimestre dalla funzione

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top