Question

J'ai une table avec les données suivantes:

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

Je voudrais écrire une requête qui produirait les éléments suivants:

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 

Je sais que cela peut être facilement réalisé en faisant d'une simple jointure de la table elle-même avec la semaine exercice précédent, mais cela ne sera pas toujours un t1.[Fiscal Week] = t2.[Fiscal Week] - 2 simple, car parfois la différence est de 3 semaines.

Je peux tirer le record max facilement avec quelque chose comme ceci:

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

Mais je suis à une perte quand il vient à abstraire pour faire le travail rejoindre.

Comment puis-je faire une auto se joindre à « la plus grande semaine fiscale qui est plus petit que l'enregistrement en cours »?

Était-ce utile?

La solution

meilleure façon de faire cela avec Sql 2005+ est d'utiliser le classement et fonctions de fenêtrage - simplement partition / commander vos données et attribuer une séquence appropriée à chaque enregistrement (dans ce cas, vous partitionnez par fiscalYear et commande par fiscalWeek sur cette fenêtre) - ressemblerait à quelque chose comme ceci:

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

Cette requête particulière ne permettrait pas l'extension à travers les frontières fiscalYear - si vous vouliez étendre à franchir ces frontières de l'année vous voulez simplement laisser tomber la « partition par » clause et « fiscalYear » condition de jointure et commander à la place l'ensemble par une combinaison du fiscalYear et fiscalWeek, quelque chose comme ceci:

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

Autres conseils

fait ce travail? La requête en ligne est un peu d'une bouchée et il y a probablement une meilleure façon de le faire ...

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 vous utilisez SQL Server 2005, vous pouvez utiliser la clause de CROSS APPLY.

Ici vous pouvez avoir une fonction d'une valeur de table, qui retournera la ligne de la semaine financière, avant celui de la ligne actuelle.

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

Et puis,

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

EDIT: Notez que je l'ai adapté le SQL en regardant un article et sans IDE
. De plus, je ne sais pas -. Comment cela fonctionnera pour la première ligne

Alors, s'il vous plaît être gentil:)

EDIT2: Permettez-moi, si ça ne marche pas du tout
. Cela me aidera à connaître -. Ne pas répondre à des choses, sans vérifier les résultats

EDIT3. J'ai supprimé le besoin de paramètre de quartier de la fonction

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top