2017-02-08 1 views
3

Ich möchte wirklich nach Pivot-Tabelle in SQL-Server fragen. Ich habe versucht, eine Abfrage zu machen, wo die Struktur so ist.Pivot-Tabelle summiert basierend auf zwischen

DECLARE @cols AS NVARCHAR(MAX) 
DECLARE @query AS NVARCHAR(MAX) 
DECLARE @tanggal_awal date 
DECLARE @tanggal_akhir date 
DECLARE @print nvarchar(MAX) 

CREATE TABLE #datatable 
(
    product_id int, 
    product_date date, 
    product_ammount int 
) 

SET @tanggal_awal = convert(date,'02-01-2017') 
SET @tanggal_akhir = convert(date,'02-27-2017') 



insert into #datatable (product_id,product_date,product_ammount) VALUES 
      (1,getdate(),100), 
      (1,getdate(),900), 
      (2,dateadd(DD,-1,getdate()),400), 
      (3,DATEADD(DD,4,getdate()),300), 
      (1,dateadd(DD,4,getdate()),200), 
      (2,dateadd(DD,2,getdate()),700), 
      (4,dateadd(DD,-3,getdate()),1000) 

--SELECT * FROM @datatable 

;WITH CTE (datelist,maxdate) AS 
(
    select min(@tanggal_awal) datelist, max(product_date) maxdate 
    from #datatable 
    union all 
    select dateadd(dd, 1, datelist), @tanggal_akhir 
    from cte 
    where datelist < maxdate 
) SELECT c.datelist 
    into #temp 
    from cte c 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(CHAR(10), datelist, 120)) 
       from #temp 
       FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)') 
       ,1,1,'') 

--SELECT d.datelist, b.product_id, SUM(b.product_ammount) 
-- FROM #temp d left join #datatable b on 
-- d.datelist between @tanggal_awal and @tanggal_akhir 
-- AND d.datelist = b.product_date 
-- GROUP BY b.product_id, d.datelist 

--select b.product_id, d.datelist, 
--    sum(b.product_ammount) PivotDate 
--    from #datatable b 
--    left join #temp d 
--    on d.datelist between @tanggal_awal and @tanggal_akhir 
--    and d.datelist = b.product_date 
--group by b.product_id, d.datelist 
--order by b.product_id 


SET @query = 'SELECT product_id, '[email protected]+' FROM 
      (
       select b.product_id, d.datelist, convert(CHAR(10), datelist, 120) PivotDate 
       from #datatable b 
       left join #temp d 
       on d.datelist between @tanggal_awal and @tanggal_akhir 
       and d.datelist = b.product_date 

      ) x 
      pivot 
      (
       count(datelist) 
       for PivotDate in (' [email protected]+ ') 
      ) p' 


EXECUTE sp_executesql @query ,N'@tanggal_awal DATE, @tanggal_akhir DATE', @tanggal_awal,@tanggal_akhir 
GO 
drop table #temp 
go 
drop table #datatable 

Das Ergebnis dieser Abfrage ist meist die Zählung der 'product_id' im jeweiligen Datum. Ich möchte jedoch die Summe der Gesamtmenge basierend auf product_ammount wie folgt erhalten.

------------------------------------- 
|product_id| 2017-01-02 | 2017-02-02| 
------------------------------------- 
|1   | 0   | 1000  | 
------------------------------------- 
|2   | 900  | 0   | 
------------------------------------- 
|3   | 700  | 0   | 
------------------------------------- 

Kann mir jemand den besten Weg geben, Join und Pivot zusammen zu behandeln, besonders für diesen Fall? vielen Dank.

--Update nach der Abfrage von Shakeer Mirza, ist das Ergebnis wie folgt.

enter image description here

können wir Gruppen es?

Antwort

2

Versuchen Sie dies unten. Ich glaube, Sie benötigen eine Pivot zu SUM von product_ammount und der qry X ändern product_ammount in Select

SET @query = 'SELECT product_id, '[email protected]+' FROM 
      (

       select b.product_id, convert(CHAR(10), datelist, 120) PivotDate, product_ammount 
       from #datatable b 
       left join #temp d 
       on d.datelist between @tanggal_awal and @tanggal_akhir 
       and d.datelist = b.product_date 


      ) x 
      pivot 
      (
       sum(product_ammount) 
       for PivotDate in (' [email protected]+ ') 
      ) p' 


EXECUTE sp_executesql @query ,N'@tanggal_awal DATE, @tanggal_akhir DATE', @tanggal_awal,@tanggal_akhir 
GO 
drop table #temp 
go 
drop table #datatable 

Update zu haben: zu ersetzen Null

DECLARE @COLS_ISNULL VARCHAR(MAX)=''; 

SELECT @COLS_ISNULL = @COLS_ISNULL +COLS_ISNULL+',' FROM (
SELECT distinct 'ISNULL('+QUOTENAME(convert(CHAR(10), datelist, 120))+',0) 'as COLS_ISNULL 
       from #temp)A 
--to remove last comma. 
SELECT @COLS_ISNULL = SUBSTRING (@COLS_ISNULL,1,LEN(@COLS_ISNULL)-1) 

und ersetzen Sie die oben @COLS_ISNULL in Select von deiner @query.

SET @query = 'SELECT product_id, '[email protected]_ISNULL+' FROM 
      (

       select b.product_id, convert(CHAR(10), datelist, 120) PivotDate, product_ammount 
       from #datatable b 
       left join #temp d 
       on d.datelist between @tanggal_awal and @tanggal_akhir 
       and d.datelist = b.product_date 


      ) x 
      pivot 
      (
       sum(product_ammount) 
       for PivotDate in (' [email protected]+ ') 
      ) p' 

Von Kommentare:

Dies ist die Ausgabe von meinem SSMS

enter image description here

+0

es funktioniert :), vielen Dank., Aber das Ergebnis ist nicht wirklich gut. –

+0

Ihre Begrüßung :) @FarisFajar –

+0

@mirza, wie gruppiert man es, da das Ergebnis nicht gruppiert ist? –

1

Ihre Anfrage kann vereinfacht werden:

SET @query = 
    'SELECT product_id, '[email protected]+' FROM 
    (
     select b.product_id, b.product_ammount, 
       convert(CHAR(10), product_date, 120) PivotDate 
     from #datatable b 
     where product_date between @tanggal_awal and @tanggal_akhir     
    ) x 
    pivot 
    (
     sum(product_ammount) 
     for PivotDate in (' [email protected]+ ') 
    ) p' 

Sie dies nicht tun muss LEFT JOIN bis #temp seit for Klausel in der pivot Operation ist, was wirklich eine Liste aller Daten zurückgibt.

+0

Ich denke, deine Antwort ist die perfekte. Danke :), BTW, wo sollte ich etwas wie coalesce (x, 0) setzen, um die Null zu entfernen? –

1

basierend auf Shakeer Mirza und Giorgos Betos Antwort für diese Frage, endlich habe ich dieses Problem gelöst. Dies ist die vollständige Abfrage für dieses Problem

DECLARE @cols AS NVARCHAR(MAX) 
DECLARE @colswithNoNulls AS NVARCHAR(MAX) 
DECLARE @query AS NVARCHAR(MAX) 
DECLARE @tanggal_awal date 
DECLARE @tanggal_akhir date 
DECLARE @print nvarchar(MAX) 

CREATE TABLE #datatable 
(
    product_id int, 
    product_date date, 
    product_ammount int 
) 

SET @tanggal_awal = convert(date,'02-01-2017') 
SET @tanggal_akhir = convert(date,'02-27-2017') 



insert into #datatable (product_id,product_date,product_ammount) VALUES 
      (1,getdate(),100), 
      (1,getdate(),900), 
      (2,dateadd(DD,-1,getdate()),400), 
      (3,DATEADD(DD,4,getdate()),300), 
      (1,dateadd(DD,4,getdate()),200), 
      (2,dateadd(DD,2,getdate()),700), 
      (4,dateadd(DD,-3,getdate()),1000) 


;WITH CTE (datelist,maxdate) AS 
(
    select min(@tanggal_awal) datelist, max(product_date) maxdate 
    from #datatable 
    union all 
    select dateadd(dd, 1, datelist), @tanggal_akhir 
    from cte 
    where datelist < maxdate 
) SELECT c.datelist 
    into #temp 
    from cte c 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(CHAR(10), datelist, 120)) 
       from #temp 
       FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)') 
       ,1,1,'') 

select @colswithNoNulls = STUFF((SELECT distinct ',ISNULL(' + QUOTENAME(convert(CHAR(10), datelist, 120)) +',''0'') '+ QUOTENAME(convert(CHAR(10), datelist, 120)) 
          from #temp 
          FOR XML PATH(''), TYPE 
          ).value('.', 'NVARCHAR(MAX)') 
          ,1,1,'') 

SET @query = 
      'SELECT product_id, '+ @colswithNoNulls+' FROM 
      (
       select b.product_id, coalesce(b.product_ammount,0) as product_ammount, 
         convert(CHAR(10), product_date, 120) PivotDate 
       from #datatable b 
       where product_date between @tanggal_awal and @tanggal_akhir         
      ) x 
      pivot 
      (
       sum(product_ammount) 
       for PivotDate in (' [email protected]+ ') 
      ) p'    


EXECUTE sp_executesql @query ,N'@tanggal_awal DATE, @tanggal_akhir DATE', @tanggal_awal,@tanggal_akhir 
GO 
drop table #temp 
go 
drop table #datatable 

die Idee von How to replace (null) values with 0 output in PIVOT ist. Die Idee selbst besteht darin, zwei verschiedene Spalten zu erzeugen, eine für nur die Spalten und eine andere für ISNULL. Hoffentlich kann dieses Problem eine Menge Probleme in naher Zukunft lösen :)

+0

Endlich hast du es. :) –

Verwandte Themen