sql >> Database >  >> RDS >> Sqlserver

Dynamische kolommen - SQL Server - Maanden als kolommen

Uw gegevens zijn al gedraaid, maar moeten op een ander niveau worden gedraaid. Ik denk dat de beste manier om dit aan te pakken is om het eerst te draaien en dan het juiste draainiveau als tweede af te handelen.

Stap 1:draai ongedaan maken

U kunt de SQL 2005 UNPIVOT gebruiken commando, of gebruik een CROSS JOIN-techniek. Hier zijn voorbeelden van beide. Let op:ik heb maanden in het midden weggelaten om het simpel te houden. Voeg ze gewoon toe.

-- 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)

Elke rij wordt 12 keer herhaald, waarna een CASE-instructie slechts één maand voor elke rij tevoorschijn komt, waardoor de gegevens netjes ongedraaid blijven.

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

Geen van beide methoden is altijd een duidelijke prestatiewinnaar. Soms werkt de ene beter dan de andere (afhankelijk van de gegevens die worden gedraaid). De UNPIVOT-methode gebruikt een filter in het uitvoeringsplan dat de CROSS JOIN niet heeft.

Stap 2:opnieuw draaien

Nu, hoe de niet-gedraaide gegevens te gebruiken. Je hebt niet gezegd hoe je iemand zal dit verbruiken, maar aangezien u de gegevens in een of ander uitvoerbestand moet plaatsen, stel ik voor SSRS (Sql Server Reporting Services) te gebruiken, dat zonder extra kosten bij SQL Server 2005 wordt geleverd.

Gebruik gewoon de Matrix report object om een ​​van de bovenstaande query's te draaien. Dit object bepaalt met plezier de gegevenswaarden die tijdens de runtime van het rapport in kolomlabels moeten worden omgezet en klinkt als precies wat u nodig hebt. Als u een kolom toevoegt die de datum precies zo opmaakt als u wilt, kunt u sorteren op de Mo-kolom, maar de nieuwe uitdrukking gebruiken als het kolomlabel.

SSRS heeft ook een breed scala aan formaten en planningsopties beschikbaar. U kunt het bijvoorbeeld een Excel-bestand laten e-mailen of een webpagina opslaan in een bestandsshare.

Laat het me weten als ik iets heb weggelaten.

Voor iedereen die de bovenstaande code in actie wil zien, hier is een creatiescript voor je:

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. Snel mySQL-klassement met spelersrang (en omringende spelers)

  2. Is het mogelijk om een ​​specifieke ORDER BY te selecteren in SQL Server 2008?

  3. Postgres - verwijder element uit jsonb-array

  4. Moet ik de strikte modus van MySQL uitschakelen?