2016-07-19 2 views
0

Ich habe eine Tabelle wie folgt:Derive Spaltenname von Datum in Zeilen und zeigt monatliche Daten in SQL-

CREATE table #yourtable 
(
    [Id] int, 
    [ColumnName] varchar(13), 
    Val1 float, 
    Val2 float, 
    StartDate datetime, 
    EndDate datetime 
); 

INSERT INTO #yourtable 
    ([Id], [ColumnName],Val1,Val2,StartDate,EndDate) 
VALUES 
    (1,'ABC12',1000,900,'2016-01-01 00:00:00','2016-01-31 23:59:59'), 
    (2,'ABC12',1100,900,'2016-02-01 00:00:00','2016-02-29 23:59:59'), 
    (3,'CDE34',1000,800,'2016-01-01 00:00:00','2016-01-31 23:59:59'), 
    (4,'EFG45',1000,700,'2016-03-01 00:00:00','2016-03-31 23:59:59'), 
    (5,'FGH56',1000,1001,'2016-02-01 00:00:00','2016-02-29 23:59:59'); 

Ich versuche, wie unten monatlichen segregierten Daten zu erhalten:

Column Name Jan  Feb  Mar 
    ABC12 1000  1100  null 
    ABC12 900  900  null 
    CDE34 1000  null  null 
    CDE34 800  null  null 
    EFG45 null  null  1000 
    EFG45 null  null  700 
    FGH56 null  1000  null 
    FGH56 null  1001  null 

Ich bin relativ neu zu sql. Vielen Dank im Voraus

+1

sql server oder mysql? –

+0

Hallo Denis, Sql Server –

Antwort

1

dies versuchen ..

SELECT * FROM (SELECT [ColumnName], 
      SUM(Val1) AS _Val, 
      CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(StartDate), - 1))) MonthCol 
      FROM #yourtable WHERE YEAR(StartDate) = 2016 
      GROUP BY StartDate,[ColumnName]) AS TP 
    PIVOT (SUM(_Val) FOR MonthCol IN ([Jan], [Feb], [Mar], [Apr], [May], [Jun], [Jul], [Aug], [Sep], [Oct], [Nov], [Dec])) AS PVTTable 
UNION 
SELECT * FROM (SELECT [ColumnName], 
      SUM(Val2) AS _Val, 
      CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(EndDate), - 1))) MonthCol 
      FROM #yourtable WHERE YEAR(EndDate) = 2016 
      GROUP BY EndDate,[ColumnName]) AS TP 
    PIVOT (SUM(_Val) FOR MonthCol IN ([Jan], [Feb], [Mar], [Apr], [May], [Jun], [Jul], [Aug], [Sep], [Oct], [Nov], [Dec])) AS PVTTable 

für dynamische Abfrage

DECLARE @MaxMonth DATE = GETDATE(); 
    DECLARE @YearData NVARCHAR(4) = CAST(YEAR(@MaxMonth) AS NVARCHAR(4)) 
    DECLARE @END_MM INT = MONTH(@MaxMonth) --End of Month 
    DECLARE @START_MM INT = 1 --Start Month of Year Data 

    DECLARE @TB_DATE AS TABLE 
    (
     ID INT IDENTITY(1,1), 
     MONTH_LIST VARCHAR(12) 
    ) 
    WHILE @START_MM <= @END_MM 
    BEGIN 
     INSERT INTO @TB_DATE (MONTH_LIST) VALUES ('['+CONVERT(VARCHAR(3),DATENAME(MONTH, DATEADD(MONTH, @START_MM-1, CAST(@END_MM AS datetime))))+']') 
     SET @[email protected]_MM+1 
    END 

    DECLARE @MM_LIST NVARCHAR(MAX) = (SELECT STUFF((SELECT ',' + MONTH_LIST 
         FROM @TB_DATE ORDER BY ID DESC 
         FOR XML PATH('')) ,1,1,'') AS Txt) 

    DECLARE @DynamicPivot AS NVARCHAR(MAX) 
    SET @DynamicPivot = N' SELECT * FROM (SELECT [ColumnName], 
      SUM(Val1) AS _Val, 
      CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(StartDate), - 1))) MonthCol 
      FROM #yourtable WHERE YEAR(StartDate) = '[email protected]+' 
      GROUP BY StartDate,[ColumnName]) AS TP 
    PIVOT (SUM(_Val) FOR MonthCol IN ('[email protected]_LIST+')) AS PVTTable 
    UNION 
    SELECT * FROM (SELECT [ColumnName], 
      SUM(Val2) AS _Val, 
      CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(EndDate), - 1))) MonthCol 
      FROM #yourtable WHERE YEAR(EndDate) = '[email protected]+' 
      GROUP BY EndDate,[ColumnName]) AS TP 
    PIVOT (SUM(_Val) FOR MonthCol IN ('[email protected]_LIST+')) AS PVTTable'; 

EXEC sp_executesql @DynamicPivot 
+0

Vielen Dank für Ihre schnelle Antwort. Es war eine große Hilfe. Wie auch immer, kann ich die Anzahl der Monate nicht dynamisch festlegen. Nehmen wir an, wenn die Daten von Jan bis Aug sind, dann werden die Zeilen von Jan bis Aug dynamisch angezeigt. Wie integriere ich diese Logik mit der obigen Abfrage? Vielen Dank im Voraus –

+0

Ja können wir, bitte versuchen Sie in Dynamic Query als meine Antwort. – taotechnocom

1

Mit pivoting:

SELECT ColumnName, 
     MAX([Jan]) as [Jan], 
     MAX([Feb]) as [Feb], 
     MAX([Mar]) as [Mar], 
     MAX([Apr]) as [Apr], 
     MAX([May]) as [May], 
     MAX([Jun]) as [Jun], 
     MAX([Jul]) as [Jul], 
     MAX([Aug]) as [Aug] 
FROM (
    SELECT Id, 
      ColumnName, 
      LEFT(DATENAME(MONTH,StartDate),3) as M, 
      [Vals], 
      [Column] 
    FROM 
    (SELECT * 
    FROM #yourtable) y 
    UNPIVOT (
     [Column] FOR Vals IN ([Val1],[Val2]) 
    )as unpvt 
    ) as s 
PIVOT (
    MAX([Column]) FOR M IN ([Jan],[Feb],[Mar],[Apr],[May],[Jun],[Jul],[Aug]) 
) as pvt 
GROUP BY ColumnName,Vals 
ORDER BY ColumnName 

Ausgang:

ColumnName Jan  Feb  Mar 
ABC12  1000 1100 NULL 
ABC12  900  900  NULL 
CDE34  1000 NULL NULL 
CDE34  800  NULL NULL 
EFG45  NULL NULL 1000 
EFG45  NULL NULL 700 
FGH56  NULL 1000 NULL 
FGH56  NULL 1001 NULL 

Mit UNPIVOT wir diese Tabellenstruktur erhalten:

Id ColumnName M Vals Column 
1 ABC12  Jan Val1 1000 
1 ABC12  Jan Val2 900 
2 ABC12  Feb Val1 1100 
2 ABC12  Feb Val2 900 
3 CDE34  Jan Val1 1000 
3 CDE34  Jan Val2 800 
4 EFG45  Mar Val1 1000 
4 EFG45  Mar Val2 700 
5 FGH56  Feb Val1 1000 
5 FGH56  Feb Val2 1001 

Also alles Vals in einer Spalte ist, dann verwenden wir PIVOT auf gewünschtes Ergebnis mit Hilfe von GROUP BY und ORDER BY zu bekommen.

Wenn es viele Vals gibt, verwenden Sie besser dynamisches SQL.

+0

Vielen Dank für Ihre Antwort. Das ist genau das, was ich wollte. Kann ich die Anzahl der Monate jedoch nicht dynamisch festlegen? Nehmen wir an, wenn die Daten von Jan bis Aug sind, dann werden die Zeilen von Jan bis Aug dynamisch angezeigt. Wie integriere ich diese Logik mit der obigen Abfrage? Vielen Dank im Voraus –

+0

Fügen Sie einfach den Monat hinzu, den Sie im Pivot- und Max-Ausdruck vom Anfang der Abfrage benötigen. – gofr1

+0

Es gibt nur 12 Monate, also denke ich, dass es besser ist, dynamisches SQL in dieser speziellen Situation zu vermeiden. Ich füge meiner Antwort noch einen Monat hinzu. – gofr1

Verwandte Themen