sql >> Databasteknik >  >> RDS >> Sqlserver

Dynamiska kolumner - SQL Server - Månader som kolumner

Din data är redan pivoterad, men måste pivoteras på en annan nivå. Jag tror att det bästa sättet att hantera detta är att avpivotera den först och sedan hantera den korrekta pivotnivån.

Steg 1:Unpivot

Du kan använda SQL 2005 UNPIVOT kommando, eller använd en CROSS JOIN-teknik. Här är exempel på båda. Observera att jag utelämnade månader i mitten för att göra det enkelt. Lägg bara till dem.

-- CROSS JOIN method (also works in SQL 2000)
SELECT
   P.Project,
   Mo =
      DateAdd(mm,
         X.MonthNum,
         DateAdd(yy, P.[Year] - 1900, '19000101')
      ),
   Amount = 
      CASE X.MonthNum
         WHEN 0 THEN Jan
         WHEN 1 THEN Feb
         WHEN 11 THEN Dec
      END
FROM
   ProjectData P
   CROSS JOIN (
      SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 11
   ) X (MonthNum)

Varje rad upprepas 12 gånger, sedan drar ett CASE-uttalande ut endast en månad för varje rad, vilket lämnar data fint opivoterad.

-- UNPIVOT method
SELECT
    P.Project,
    Mo =
       DateAdd(mm,
          Convert(int, P.MonthNum),
          DateAdd(yy, P.[Year] - 1900, '19000101')
       ),
    P.Amount
FROM
   (
      SELECT Project, [Year], [0] = Jan, [1] = Feb, [11] = Dec
      FROM ProjectData
   ) X UNPIVOT (Amount FOR MonthNum IN ([0], [1], [11])) P

DROP TABLE ProjectData

Ingen av metoderna är en klar prestationsvinnare hela tiden. Ibland fungerar den ena bättre än den andra (beroende på vilken data som pivoteras). UNPIVOT-metoden använder ett filter i exekveringsplanen som CROSS JOIN inte gör.

Steg 2:Pivotera igen

Nu, hur man använder opivoterad data. Du sa inte hur du någon kommer att konsumera detta, men eftersom du måste lägga in data i en utdatafil av något slag, föreslår jag att du använder SSRS (Sql Server Reporting Services), som kommer med SQL Server 2005 utan extra kostnad.

Använd bara matrisen rapportera objekt för att pivotera en av frågorna ovan. Det här objektet bestämmer med glädje vilka datavärden som ska göras till kolumnetiketter när rapporten körs och låter som precis vad du behöver. Om du lägger till en kolumn som formaterar datumet precis som du vill kan du sortera efter Mo-kolumnen, men använd det nya uttrycket som kolumnetikett.

SSRS har också en mängd olika format och schemaläggningsalternativ tillgängliga. Du kan till exempel låta den skicka en Excel-fil via e-post eller spara en webbsida till en filresurs.

Meddela mig om jag har utelämnat något.

För alla som vill se koden ovan i aktion, här är ett skript för dig:

USE tempdb

CREATE TABLE ProjectData (
    Project varchar(10),
    [Year] int,
    Jan decimal(15, 2),
    Feb decimal(15, 2),
    Dec decimal(15, 2)
)

SET NOCOUNT ON

INSERT ProjectData VALUES ('11-11079', 2008, 0.0, 0.0, 75244.90)
INSERT ProjectData VALUES ('11-11079', 2009, 466.0, 0.0, 0.0)
INSERT ProjectData VALUES ('11-11079', 2010, 855.0, 0.0, 0.0)
INSERT ProjectData VALUES ('01-11052', 2009, 56131.0, 0.0, 0.0)


  1. Returnera ett standardvärde om en rad inte hittas

  2. Kombinerade 2 kolumner till en SQL-kolumn

  3. SLIPP TABELL OM FINNS i MySQL

  4. Krävs COMMIT efter varje UTFÖR OMEDELBART?