Frage

Ich habe eine Tabelle mit den folgenden Daten:

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

Ich möchte eine Abfrage schreiben, die die folgende erzeugen würde:

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 

Ich weiß, das kann einfach, indem Sie ein einfache die Tabelle mit der vorherige Geschäft Woche zu ihnen kommen erzielt werden, jedoch wird dies nicht immer eine einfache t1.[Fiscal Week] = t2.[Fiscal Week] - 2 sein, weil manchmal der Unterschied 3 Wochen ist.

Ich kann die maximale Satz leicht mit etwas wie folgt ziehen:

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

Aber ich bin ratlos, wenn es darum geht, sie zu abstrahieren die Join-Arbeit zu machen.

Wie kann ich ein Selbst auf „der größte Geschäft Woche, die kleiner ist als der aktuelle Datensatz ist“ join?

War es hilfreich?

Lösung

Der einfachste Weg, dies mit Sql 2005+ zu tun ist, die verwenden Ranking und Windowing-Funktionen - einfach Partition / Ihre Daten bestellen und eine entsprechende Sequenz zu jeder Datensatz zuweisen (in diesem Fall Sie die Partitionierung von FiscalYear und Bestellung von fiscalWeek über das Fenster) - würde wie folgt aussehen:

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

Diese besondere Abfrage erlauben würde, nicht Erweiterung über FiscalYear Grenzen - wenn Sie dieses Jahr, Grenzen überschreiten verlängern wollen würden Sie einfach die „Partition“ -Klausel und „FiscalYear“ Join-Bedingung fallen wollen und stattdessen durch eine Kombination des festgelegte Reihenfolge der FiscalYear und fiscalWeek, so etwas wie folgt aus:

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

Andere Tipps

funktionierts? Die Inline-Abfrage ist ein bisschen wie ein Schluck und gibt es wahrscheinlich einen besseren Weg, es zu tun ...

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

Wenn Sie SQL Server 2005 verwenden, können Sie CROSS APPLY-Klausel verwenden.

Hier konnte man eine Tabelle bewertet Funktion hat, die die Zeile für das Geschäft Woche zurück, vor das man in der aktuellen Zeile.

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

Und dann,

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

EDIT: Beachten Sie, dass ich durch einen Blick auf einen Artikel, der die SQL angepasst haben und ohne eine IDE
. Auch ich weiß nicht, -., Wie es für die erste Zeile arbeiten

Also, bitte Art:)

EDIT2: Lassen Sie mich wissen, wenn es überhaupt nicht arbeiten
. Das wird mir helfen, zu wissen, -. Dinge nicht zu beantworten, ohne die Ergebnisse überprüfen

EDIT3:. Ich habe die Notwendigkeit Quarter Parameter aus der Funktion entfernt

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top