2016-05-31 20 views
1

ich eine SQL Server 2008 Express-Tabelle wie folgt aus:SQL Server: anzeigen Zeilen als Spalten/Pivot

rno gid uid dat   origamt disamt 
----------------------------------------------- 
1  AA a  12-05-2016 200  210 
2  AA b  12-05-2016 300  305 
3  AA c  12-05-2016 150  116 
4  BB a  12-05-2016 120  125 
5  BB c  12-05-2016 130  136 
6  CC a  12-05-2016 112  115 
7  CC b  12-05-2016 135  136 

und so weiter für andere Daten

ich es so zeigen wollen:

sno  dat  gid a_orig a_dis b_orig b_dis c_orig c_dis ..... 
1 12-05-2016 AA 200  210  300  305  150  116 
2 12-05-2016 BB 120  125  0  0  130  136 
3 12-05-2016 CC 112  115  135  136  0  0 

HINWEIS: die Werte der uid sind nicht festgelegt, so können sie dynamisch variieren, so, a_orig, a_dis, b_orig, b_dis, etc. können nicht in SQL fest einprogrammiert werden.

HINWEIS: Bei jedem Datum werden aufgrund des kartesischen Produkts von gid und uid etwa 300 Zeilen erwartet. und ich werde datumsweise suchen, indem ich die LIKE-Klausel implementiere, da der Datentyp dat Spalte varchar(50) ist.

Hinweis: Ich würde Datentyp origamt und disamt bevorzugt varchar(50) statt Decimal(18, 0) zu sein, aber es ist nicht Zwang.

Ich habe versucht, PIVOT zu verwenden, indem ich von mehreren Artikeln, die hier auf stackoverflow und anderer Website gepostet wurden, Bezug nahm, aber die Arbeit nicht vollständig erledigen konnte.

Hier ist, was ich versucht und bekam fast gute Ergebnisse mit festen uid und nur geholt origamt:

select * 
from 
(
    select gid, uid, dat, origamt 
    from vamounts 
) as src 
pivot 
(
    sum(origamt) 
    for uid IN (a, b) 
) as piv; 

Bitte helfen Sie mir mit der geringsten sperrig mögliche Lösung für dieses Problem. Ich bevorzuge die geringsten Codezeilen und die geringste Komplexität.

+0

Bitte geben Sie eine SQL-Anweisung und ein Beispiel Ihrer Tabellenstruktur mit einigen Dummy-Daten an. Diese Frage ist nicht gut gestaltet. – Mitrucho

+1

*** WARUM *** möchten Sie einen * offensichtlich * numerischen Wert wie 'origamt' als String speichern? ** Tun Sie dies nicht ** Verwenden Sie die ** am besten geeignet ** Datentyp immer - wenn Sie Nummern speichern - einen ** ** numerischen Datentyp verwenden - keine Strings !! –

+0

Hallo Mitrucho. Entschuldigung für das Problem. Jetzt habe ich den Post für Klarheit umgestaltet (vielleicht habe ich). –

Antwort

0

Sie benötigen dynamische SQL für dieses Zeug.

Auf den ersten Tabelle mit Ihren Daten erstellen:

CREATE TABLE #temp (
    rno int, 
    gid nvarchar(10), 
    [uid] nvarchar(10), 
    dat date, 
    origamt int, 
    disamt int 
) 

INSERT INTO #temp VALUES 
(1,  'AA', 'a',  '12-05-2016', 200,  210), 
(2,  'AA', 'b',  '12-05-2016', 300,  305), 
(3,  'AA', 'c',  '12-05-2016', 150,  116), 
(4,  'BB', 'a',  '12-05-2016', 120,  125), 
(5,  'BB', 'c',  '12-05-2016', 130,  136), 
(6,  'CC', 'a',  '12-05-2016', 112,  115), 
(7,  'CC', 'b',  '12-05-2016', 135,  136) 

Und dann Variablen mit Spalten deklarieren:

DECLARE @columns nvarchar(max), @sql nvarchar(max), @columns1 nvarchar(max), @columnsN nvarchar(max) 
--Here simple columns like [a],[b],[c] etc 
SELECT @columns =STUFF((SELECT DISTINCT ','+QUOTENAME([uid]) FROM #temp FOR XML PATH('')),1,1,'') 
--Here with ISNULL operation ISNULL([a],0) as [a],ISNULL([b],0) as [b],ISNULL([c],0) as [c] 
SELECT @columnsN = STUFF((SELECT DISTINCT ',ISNULL('+QUOTENAME([uid])+',0) as '+QUOTENAME([uid]) FROM #temp FOR XML PATH('')),1,1,'') 
--Here columns for final table orig.a as a_orig, dis.a as a_dis,orig.b as b_orig, dis.b as b_dis,orig.c as c_orig, dis.c as c_dis 
SELECT @columns1 = STUFF((SELECT DISTINCT ',orig.'+[uid] + ' as ' +[uid]+ '_orig, dis.'+[uid] + ' as ' +[uid]+ '_dis' FROM #temp FOR XML PATH('')),1,1,'') 

Und Hauptabfrage:

SELECT @sql = ' 
SELECT orig.gid, 
     orig.dat, 
     '[email protected]+' 
FROM (
     SELECT gid, dat, '[email protected]+' 
     FROM (
      SELECT gid, [uid], LEFT(dat,10) as dat, origamt 
      FROM #temp 
      ) as p 
     PIVOT (
     SUM(origamt) FOR [uid] in ('[email protected]+') 
     ) as pvt 
    ) as orig 
LEFT JOIN (
     SELECT gid, dat, '[email protected]+' 
     FROM (
      SELECT gid, [uid], LEFT(dat,10) as dat, disamt 
      FROM #temp 
      ) as p 
     PIVOT (
     SUM(disamt) FOR [uid] in ('[email protected]+') 
     ) as pvt 
    ) as dis 
    ON dis.gid = orig.gid and dis.dat = orig.dat' 

EXEC(@sql) 

Ausgang:

gid dat   a_orig a_dis b_orig b_dis c_orig c_dis 
AA 2016-12-05 200  210  300  305  150  116 
BB 2016-12-05 120  125  0  0  130  136 
CC 2016-12-05 112  115  135  136  0  0 
+0

Hallo. Ich werde die Zeichenfolge mit den erforderlichen Feldern formatieren, bevor Sie es über asp.net mit C# ausführen. Also, bitte sagen Sie mir, was ist der erwartete Wert von Spalten1, SpaltenN und Spalten, so dass ich sie durch string.Format() im Frontend stopfen kann. –

+0

Erwartete Werte werden in Kommentaren für jede Variable demonstriert. – gofr1

+0

Das gleiche Problem? Warum ersetzen Sie Variablen? Sie können diese Abfrage in die gespeicherte Prozedur einfügen und dann die Tabelle daraus abrufen. Die Antwort auf Ihre Hauptfrage - wie Sie diese Daten mit dynamischen (no-not-to-count-Spalten) mit Pivot bekommen, und '0' anstelle von' NULL' ist gegeben. Wenn Sie noch weitere Fragen haben, stellen Sie bitte eine neue Frage. – gofr1

0

A beitreten könnte

declare @t table (rno int, gid varchar(2), uid varchar(1), dat varchar(10), origamt int, disamt int) 
insert into @t 
values 
(1,  'AA', 'a',  '12-05-2016', 200,  210), 
(2 , 'AA', 'b',  '12-05-2016', 300,  305), 
(3 , 'AA', 'c',  '12-05-2016', 150,  116), 
(4 , 'BB', 'a',  '12-05-2016', 120,  125), 
(5 , 'BB', 'c',  '12-05-2016', 130,  136), 
(6 , 'CC', 'a',  '12-05-2016', 112,  115), 
(7 , 'CC', 'b',  '12-05-2016', 135,  136) 

    select -- piv.*,piv2.* 
      piv.gid,piv.dat 
      ,piv.a as a_org 
      ,piv2.a as a_dis 
      ,piv.b as b_org 
      ,piv2.b as b_dis 
      ,piv.c as c_org 
      ,piv2.c as c_dis 
    from 
    (
     select gid, uid, dat, origamt 
     from @t 
    ) as src 
    pivot 
    (
     sum(origamt) 
     for uid IN ([a],[b],[c]) 
    ) as piv 
    join 
    (select piv2.* 
    from 
    (
     select gid, uid, dat, disamt 
     from @t 
    ) as src 
    pivot 
    (
     sum(disamt) 
     for uid IN ([a],[b],[c]) 
    ) as piv2 
    ) piv2 
    on piv2.gid = piv.gid and piv2.dat = piv.dat 

Dies ist ein POC helfen würden Sie dynamische SQL beschäftigen sich mit der variablen Anzahl von uids verwenden. Lassen Sie es mich wissen, wenn Sie nicht wissen, wie man dynamisches SQL verwendet, und ich werde ein Beispiel für Sie aufarbeiten.

+0

Hi. Die Lösung scheint viel näher, aber mit einem großen Problem. Jedes GID wird im Resultset angezeigt, aber jeder alternative Datensatz wird mit Nullwerten wiederholt. Z.B. a kommt einmal, b kommt zweimal (einmal mit Wert, 2. mit NULL), c kommt einmal, d kommt zweimal (einmal mit Wert, 2. mit NULL) ..... so, obwohl es in der Quelltabelle keine Wiederholung gibt . Ja, ich brauche die Spalten dynamisch hinzugefügt werden, ohne dass ich diese Lösung jedoch nicht verwenden kann, ich werde diese Abfrage von Frontend in asp.net auslösen und es in einer Gridview so zeigen, kann ich eine String-Variable als Parameter übergeben. Freundliche Rückmeldung. –

+0

Jedes select erzeugt eine temporäre Tabelle - Nullen werden generiert, wenn kein Ergebnis vorliegt (normal für SQL). Wenn Sie 0 für Nullen ersetzen möchten, verwenden Sie ISNULL. –

+0

Hey Mike, ich habe versucht, die Lösung, aber es hat nicht funktioniert für mich. Hier wurden für jedes GID mehrere Zeilen zurückgegeben. Mein GID hat 5 Instanzen in der Tabelle mit 5 verschiedenen Uids und im Endergebnis gab es mir 5 Zeilen für GID. Bitte sagen Sie mir, wie ich einen Schnappschuss veröffentlichen kann. Ich möchte die Ergebnisse teilen. –

1

Errr, nein. Sie können Ihre gewünschte Tabelle nicht mit SQL generieren. Dies ist keine gültige Pivot-Tabelle.

"the values of uid are not fixed, they may vary dynamically, so, a_orig, a_dis, b_orig, b_dis, etc cannot be hardcoded into SQL."

Entschuldigung, das ist auch nicht möglich. Sie müssen die genauen Werte angeben, die als Spaltenüberschriften platziert werden sollen. Wenn Sie eine SELECT-Anweisung schreiben, müssen Sie die Namen der Spalten (Felder) angeben, die Sie zurückgeben. Es gibt keinen Weg um dies herum.

jedoch unten sind die Schritte erforderlich, um eine „gültige“ SQL Server Pivot-Tabelle aus Ihren Daten zu erstellen:

enter image description here

Ich habe zugeben bekam, als ich vor kurzem mein erstes PIVOT musste schreiben in SQL Server habe ich auch wie verrückt gegoogelt, aber nicht verstanden, wie man es schreibt.

Allerdings habe ich schließlich herausgefunden, was Sie tun müssen, also hier ist die Schritt-für-Schritt-Anleitung, die Sie nirgendwo anders finden ..!

(Readers diese Anweisungen leicht anpassen können, mit Ihren eigenen Daten zu verwenden!)

1. Ihre Beispieldaten erstellen

Wenn Sie erwarten Leser auf Ihre Frage zu antworten, sollten Sie zumindest Geben Sie ihnen das SQL, um Ihre Beispieldaten zu erstellen, damit sie etwas zum Arbeiten haben.

So, hier ist, wie ich die Daten in Ihrer Frage gezeigt schaffen würde:

CREATE TABLE tblSomething 
(
    [gid] nvarchar(100), 
    [uid] nvarchar(100), 
    [dat] datetime, 
    [origamt] int, 
    [disamt] int 
) 
GO 

INSERT INTO tblSomething VALUES ('AA', 'a', '2016-05-12', 200, 210) 
INSERT INTO tblSomething VALUES ('AA', 'b', '2016-05-12', 300, 305) 
INSERT INTO tblSomething VALUES ('AA', 'c', '2016-05-12', 150, 116) 
INSERT INTO tblSomething VALUES ('BB', 'a', '2016-05-12', 120, 125) 
INSERT INTO tblSomething VALUES ('BB', 'c', '2016-05-12', 130, 136) 
INSERT INTO tblSomething VALUES ('CC', 'a', '2016-05-12', 112, 115) 
INSERT INTO tblSomething VALUES ('CC', 'b', '2016-05-12', 135, 136) 
GO 

2. eine SQL-Abfrage schreiben, die drei Spalten gibt genau

Die erste Spalte die Werte enthalten, die erscheint in der linken Spalte Ihrer PIVOT-Tabelle.

Die zweite Spalte enthält die Liste der Werte, die in der oberen Zeile erscheinen.

Die Werte in der dritten Spalte werden basierend auf den Zeilen-/Spaltenüberschriften in Ihrer PIVOT-Tabelle positioniert.

Okay, hier ist die SQL, dies zu tun:

SELECT [gid], [uid], [origamt] 
FROM tblSomething 

Dies ist der Schlüssel zu einem PIVOT verwenden. Ihre Datenbankstruktur kann so schrecklich kompliziert sein, wie Sie möchten, aber wenn Sie eine PIVOT verwenden, können Sie nur mit genau drei Werten arbeiten. Nicht mehr und nicht weniger.

Also, hier ist, was diese SQL zurückgibt. Unser Ziel ist es, eine Pivot-Tabelle, die (nur) diese Werte zu schaffen:

eine Liste der unterschiedlichen Werte für die Kopfzeile

Beachten Sie, wie in der Pivot-Tabelle I

enter image description here

3. Finden Ich habe das Ziel zu erstellen, ich habe drei Spalten (Felder) genannt a, b und c. Dies sind die drei eindeutigen Werte in Ihrer Spalte [uid].

Also, um ein Komma verketteten Liste dieser einzigartigen Werte zu bekommen, ich diese SQL verwenden können:

DECLARE @LongString nvarchar(4000) 

SELECT @LongString = COALESCE(@LongString + ', ', '') + '[' + [uid] + ']' 
FROM [tblSomething] 
GROUP BY [uid] 

SELECT @LongString AS 'Subquery' 

Wenn ich dies gegen Ihre Daten laufen, hier ist was ich bekommen:

enter image description here

Jetzt schneiden Sie diesen Wert ein: Wir müssen ihn zweimal in unserem allgemeinen SQL SELECT-Befehl platzieren, um die Pivot-Tabelle zu erstellen.

4. Setzen sie alle zusammen

Dies ist der schwierige Bit.

Sie benötigen eine SQL-Befehl aus Schritt 2 und das Ergebnis aus Schritt 3 in einen einzigen SELECT Befehl zu kombinieren.

Hier ist, was Ihre SQL aussehen würde:

SELECT [gid], 
     -- Here's the "Subquery" from part 3 
     [a], [b], [c] 
FROM (
    -- Here's the original SQL "SELECT" statement from part 2 
    SELECT [gid], [uid], [origamt] 
    FROM tblSomething 

) tmp ([gid], [uid], [origamt]) 
pivot (
    MAX([origamt]) for [uid] in (
     -- Here's the "Subquery" from part 3 again 
     [a], [b], [c] 
    ) 
) p 

... und hier ist ein verwirrendes Bild, das zeigt, wo die Komponenten kommen, und die Ergebnisse dieser Befehl ausgeführt wird.

enter image description here

Wie Sie der Schlüssel dazu sehen können, ist, dass SELECT Anweisung in Schritt 2, und in diesem Befehl Ihre drei ausgewählten Felder an der richtigen Stelle setzen.

Und, wie ich bereits sagte, sind die Spalten (Felder) in der Pivot-Tabelle aus den in Schritt erhaltenen Werte 3:

[a], [b], [c] 

Sie könnten natürlich einen Teil dieser Werte verwenden. Vielleicht möchten Sie einfach die PIVOT Werte für [a], [b] sehen und [c] ignorieren.

Puh!

Also, das ist wie eine Pivot-Tabelle aus Ihren Daten zu erstellen.

I will prefer least lines of code and least complexity.

Ja, viel Glück auf diesem .. !!!

5. Zusammenführen von zwei Pivot-Tabellen

Wenn Sie wirklich wollten, könnten Sie den Inhalt zweier solcher Pivot-Tabellen zusammenführen, um die genauen Ergebnisse zu erhalten Sie suchen.

Dies ist leicht genug, um SQL für Shobhit selbst zu schreiben.

enter image description here

+0

Hallo. Ich schätze deine Arbeit. Aber ich konnte die Werte von Origin und Dists nicht sehen. Es werden nur Originalvorlagen angezeigt. Können wir beide nicht bekommen? –

+0

Ja, indem zwei Pivot-Tabellen zusammengeführt werden. Dies ist sehr einfach für Sie selbst zu schreiben. –

+0

@MikeGledhill Schöne Antwort, ich denke du solltest es gepostet hinterlassen. Gute Erklärung. Ich habe es nach dem Lesen hochgestuft :) – gofr1