2016-03-24 20 views
1

Ich habe die ähnliche Frage beim letzten Mal mit mysql gepostet. Aber dieses Mal möchte ich die gesamten Pivot-Werte mit SQL Server erhalten. Ich poste auch meinen Code. pls überprüfenPivot insgesamt mit SQL Server

DB Schema ===

DATABASE Test erstellen;

CREATE TABLE [dbo].[RAccounts_Receivable](
    [id] [int] NOT NULL, 
    [trntypename] [nvarchar](max) NULL, 
    [datecreated] [date] NULL, 
    [AmountDue] [decimal](18, 0) NULL) ; 

INSERT INTO [dbo].[RAccounts_Receivable] 
(id, trntypename,datecreated,AmountDue) 
VALUES 
(1, 'Pay Bills', '2016-01-02', 50), 
(2, 'Pay Bills', '2016-01-10', 60), 
(3, 'Sales Returns', '2016-01-20', 30), 
(4, 'Sales Returns', '2016-01-15', 20), 
(5, 'Pay Bills', '2016-02-15', 10), 


(6, 'Sales Returns', '2016-02-20', 20), 
(7, 'Sales Returns', '2016-02-15', 10) 

-Code bisher

SELECT * FROM 
      (SELECT FORMAT(datecreated,'yyyyMM') AS date 
      ,SUM(AmountDue) AS AmountDue 
      ,trntypename 
    FROM RAccounts_Receivable 
    WHERE 
      (trntypename='Pay Bills' OR trntypename='Sales Return') 
      AND datecreated >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-7, 0) 
      GROUP By [trntypename],FORMAT(datecreated,'yyyyMM')) AS Basedata 

PIVOT 
(
    SUM(AmountDue) FOR date IN ([201601],[201602]) 
) AS p 

Ergebnisse bisher

trntypename | 201601 | 201602 

Pay Bills | 110 | 10 
Sales Return| 50  | 30 

erwarteten Ergebnisse

trntypename | 201601 | 201602 | total 

Pay Bills | 110 | 10  | 120 
Sales Return| 50  | 30  | 80 
total  | 160 | 40  | 200 

noch bin ich Summen nicht in der Lage zu bekommen.

Antwort

1

Der folgende Code funktioniert Feinheiten. Ich habe eine temporäre Tabelle erstellt, die Sie durch Ihren Tabellennamen ersetzen können;

WITH CodeSoFar AS(
SELECT * FROM 
     (SELECT CONVERT(nvarchar(6), datecreated,112) AS date 
     ,SUM(AmountDue) AS AmountDue 
     ,trntypename 
     FROM ##RAccounts_Receivable 

WHERE (trntypename='Pay Bills' OR trntypename='Sales Returns') 
     AND datecreated >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-7, 0) 
     GROUP By [trntypename],CONVERT(nvarchar(6), datecreated,112) 
     ) AS ABC 

PIVOT 
(
    SUM(AmountDue) FOR date IN ([201601],[201602]) 
) AS p 
) 
SELECT *,[201601]+[201602] AS Total FROM CodeSoFar 
UNION 
SELECT 'Total' AS Total,SUM([201601]) AS '201601',SUM([201602]) AS '201602',Sum([201601]+[201602]) 
FROM CodeSoFar 
+0

Ich bedaure es nicht gut formatiert ist, aber es funktioniert gut – JonWay

+0

Dank für die Antwort. Leider scheint das bei mir nicht zu funktionieren. {{SELECT *, [201601] + [201602] AS Gesamt FROM RAccounts_Receivable UNION SELECT 'Gesamt' AS Gesamt, SUM ([201601]) AS '201601', SUM ([ 201602]) AS '201602', Summe ([201601] + [201602]) FROM RAccounts_Receivable}} gibt mir einen Fehler – Ja22

+0

ich bevorzuge die ROLLUP Funktion seit [201601], [201602] sind dynamische Spalten – Ja22

0

Ich würde meine Abfrage bilden, um so etwas zu sehen.

SELECT CASE WHEN GROUPING(trntypename) = 1 THEN 'Total' ELSE trntypename END AS trntypename, 
     SUM(CASE WHEN FORMAT(datecreated,'yyyyMM') = '201601' THEN AmountDue END) AS [201601], 
     SUM(CASE WHEN FORMAT(datecreated,'yyyyMM') = '201602' THEN AmountDue END) AS [201602], 
     SUM(AmountDue) Total 
FROM RAccounts_Receivable 
WHERE (trntypename = 'Pay Bills' 
     OR trntypename = 'Sales Returns') 
     AND datecreated >= DATEADD(month,DATEDIFF(month,0,GETDATE()) - 7,0) 
GROUP BY ROLLUP([trntypename]) 
ORDER BY CASE WHEN GROUPING(trntypename) = 1 THEN '1' ELSE 0 END 

Die Gesamtlinie durch Verwendung ROLLUP() erstellt wird, werden die anderen Summen erzeugt diese dynamisch mit SUM(CASE)

Um zu generieren. Sie können so etwas verwenden.

DECLARE @CaseQuery NVARCHAR(MAX) = 'SUM(CASE WHEN FORMAT(datecreated,''yyyyMM'') = ''<<dateval>>'' THEN AmountDue END) AS [<<dateval>>]', 
     @SelectQuery NVARCHAR(MAX), 
     @Sql NVARCHAR(MAX) 

SELECT @SelectQuery = COALESCE(@SelectQuery + ',', '') + REPLACE(@CaseQuery, '<<dateval>>', FORMAT(datecreated,'yyyyMM')) 
FROM [dbo].[RAccounts_Receivable] 
WHERE datecreated >= DATEADD(month,DATEDIFF(month,0,GETDATE()) - 7,0) 
GROUP BY FORMAT(datecreated,'yyyyMM') 
ORDER BY FORMAT(datecreated,'yyyyMM') 

SET  @Sql = ' 
    SELECT CASE WHEN GROUPING(trntypename) = 1 THEN ''Total'' ELSE trntypename END AS trntypename, ' + 
      @SelectQuery + ', 
      SUM(AmountDue) Total 
    FROM RAccounts_Receivable 
    WHERE (trntypename = ''Pay Bills'' 
      OR trntypename = ''Sales Returns'') 
      AND datecreated >= DATEADD(month,DATEDIFF(month,0,GETDATE()) - 7,0) 
    GROUP BY ROLLUP([trntypename]) 
    ORDER BY CASE WHEN GROUPING(trntypename) = 1 THEN 1 ELSE 0 END 
' 
EXEC (@Sql) 

Die Variablen werden verwendet, um die SUM(CASE) und die SQL zu erstellen, die von EXEC(@SQL) Aufruf ausgeführt wird

+0

# JamieD77 wow vielen Dank. Jetzt bekomme ich das erwartete Ergebnis in SQL SEVER. Aber ich möchte den gegebenen Code in PHP $ tsql = "" einbetten, um Ergebnisse im Browser anzuzeigen (ich verwende die PDO-Klasse). Erhalte diesen Fehler "SQLSTATE [IMSSP]: Das aktive Ergebnis für die Abfrage enthält keine Felder.1" Sollte ein Problem mit Zitaten sein. – Ja22

+0

@ Ja22 haben Sie darüber nachgedacht, dies nur eine gespeicherte Prozedur zu machen? – JamieD77

0
SELECT * FROM 
      (SELECT FORMAT(datecreated,'yyyyMM') AS date 
      ,SUM(AmountDue) AS AmountDue 
      ,trntypename 
    FROM RAccounts_Receivable 
    WHERE 
      (trntypename='Pay Bills' OR trntypename='Sales Return') 
      AND datecreated >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-7, 0) 
      GROUP By [trntypename],FORMAT(datecreated,'yyyyMM')) AS Basedata 

PIVOT 
(
    SUM(AmountDue) FOR date IN ([201601],[201602]) 
) AS p 

union 

SELECT 'total',sum([201601]) as '201601',sum([201602]) as '201602' FROM 
      (SELECT FORMAT(datecreated,'yyyyMM') AS dt 
      ,SUM(AmountDue) AS [AmountDue] 
      ,trntypename 
    FROM RAccounts_Receivable 
    WHERE 
      (trntypename='Pay Bills' OR trntypename='Sales Return') 
      AND datecreated >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-7, 0) 
      GROUP By [trntypename],FORMAT(datecreated,'yyyyMM')) AS Basedata 

PIVOT 
(
    SUM(AmountDue) FOR dt IN ([201601],[201602]) 
) AS p