2016-03-24 30 views
1

Son kez mysql kullanarak benzer bir soru gönderdim. Ama bu sefer SQL sunucusunu kullanarak toplam pivot değerlerini almak istiyorum. Kodumu da gönderiyorum. lütfenSQL Server ile pivot toplamı

DB Şema === kontrol

VERİTABANI testini CREATE;

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) 

Kod bugüne kadar

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 

Sonuçlar şu ana kadar

trntypename | 201601 | 201602 

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

beklenen sonuçlar

trntypename | 201601 | 201602 | total 

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

hala toplamlarını almak kuramıyorum.

cevap

1

Kod feryat, para cezalarıyla çalışır. Tablo adınızı ile değiştirebileceğiniz geçici bir tablo oluşturdum;

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

EXEC(@SQL) arayarak yürütülecektir SUM(CASE) ve SQL oluşturmak için kullanılır Ben buna güzel biçimlendirilmemiş üzgünüm ama cevap için ince – JonWay

+0

sayesinde çalışma. Maalesef bu benim için çalışıyor gibi görünmüyor. {{SELECT *, [201601] + [201602] Toplamda RAccounts_Receivable UNION SELECT 'Toplam' AS Toplam, SUM ([201601]) AS '201601', SUM ([ 201602]) AS '201602', Sum ([201601] + [201602]) FROM RAccounts_Receivable}} bana bir hata veriyor – Ja22

+0

[201601], [201602] dinamik sütunlar – Ja22

0

Böyle bir şeye bakmak için sorgumu oluşturabilirim.

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 

toplam hat

ROLLUP() kullanılarak oluşturulur, diğer toplamları dinamik bu oluşturmak için, SUM(CASE)

kullanılarak oluşturulur. Böyle bir şey kullanabilirsiniz.

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) 

değişkenler

+0

# JamieD77 wow için ne kadar çok teşekkür ederim. Şimdi SQL SEVER'de beklenen sonucu alıyorum. Ancak tarayıcıdaki sonuçları görüntülemek için verilen kodu php $ tsql = "" içine gömmek istiyorum (PDO sınıfını kullanıyorum). Bu hatayı alıyorum "SQLSTATE [IMSSP]: Sorgu için etkin sonuç hiçbir alan içermiyor.1" Teklifler ile ilgili bir sorun olmalı. – Ja22

+0

@ Ja22 Bunun yerine saklanmış bir prosedürü yapmayı düşündünüz mü? – 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