Frage

Ich arbeite an versucht, einen Bericht von ein paar Datenbank-Tabellen zu erzeugen. Die vereinfachte Version wie folgt aussieht

Campaign
----------
CampaignID

Source
-----------------------
Source_ID | Campaign_ID

Content
---------------------------------------------------------
Content_ID | Campaign_ID | Content_Row_ID | Content_Value

Der Bericht muss wie folgt lesen:

CampaignID - SourceID - ContentRowID(Value(A)) - ContentRowID(Value(B))

Wo ContentRowID (Wert (A)) bedeutet "eine Zeile findet die eine CampaignID gegeben hat, und eine ContentRowId von "A" und dann die ContentValue erhält für diese Zeile"

Im Wesentlichen habe ich auf „Pivot“ (Ich denke, das ist der richtige Begriff) die Zeilen in Spalten ...

Es ist eine Oracle 10g Datenbank ...

Irgendwelche Vorschläge?

War es hilfreich?

Lösung

Dies ist mein erster Stich an sie. Refinement kommen, wenn ich mehr über den Inhalt der Content-Tabelle kennen.

Zunächst müssen Sie eine temporäre Tabelle:

CREATE TABLE pivot (count integer);
INSERT INTO pivot VALUES (1);
INSERT INTO pivot VALUES (2);

Jetzt sind wir bereit, abzufragen.

SELECT campaignid, sourceid, a.contentvalue, b.contentvalue
FROM content a, content b, pivot, source
WHERE source.campaignid = content.campaignid
AND pivot = 1 AND a.contentrowid = 'A'
AND pivot = 2 AND b.contentrowid = 'B'

Andere Tipps

Bill Karwin erwähnt, aber ich denke, das ist sehr deutlich darauf hingewiesen zu werden verdient:

SQL nicht tun, was Sie fragen nach, so dass jede „Lösung“ Sie bekommen wird eine Flickschusterei sein.

Wenn Sie wissen , das ist sicher, es ist immer auf einer Oracle 10 laufen gehen, dann sicher, Walter Mitty der Kreuztabelle könnte es tun. Der richtige Weg, es zu tun, ist die einfachste Kombination von Sortierreihenfolge in der Abfrage und Anwendungscode zu arbeiten, um es zu legen rechts.

  • Es funktioniert auf anderen Datenbanksystemen,
  • es keine Gefahr besteht, keine anderen Schichten crapping aus (Ich erinnere mich, MySQL ein Problem mit> 255 Spalten zum Beispiel haben. Sind Sie sicher, dass Sie Interface-Bibliothek sowie der db meistert selbst?)
  • es ist (in der Regel) nicht, dass es sehr viel schwieriger.

Wenn Sie möchten, können Sie sich für die Content_Row_IDs fragen, dann fragen für was auch immer Zeilen, die Sie benötigen, geordnet nach CampaignID, ContentRowID, die Sie würde jede (bestückt) Zelle in von links nach rechts, line-by -Linie um.


Ps.

Es gibt eine Reihe von Sachen, die der moderne Mensch denkt, sollte SQL haben / tun, dass ist einfach nicht da. Dies ist einer, Bereiche erzeugt wird, ist eine andere, rekursive Schließung, parametrischer ORDER BY, standardisierte Programmiersprache ... die Liste geht weiter. (Wenn auch zugegebenermaßen gibt es einen Trick für ORDER BY)

Wenn Sie nicht über eine dynamische Anzahl der Spalten und Ihre Datenmenge nicht zu groß Sie dies tun könnten ...

SELECT CampaignID, SourceID, 
   (SELECT Content_Value FROM Content c 
      WHERE c.Campaign_ID=s.Campaign_ID 
      AND Content_Row_ID = 39100 
      AND rownum<=1) AS Value39100,
   (SELECT Content_Value FROM Content c 
      WHERE c.Campaign_ID=s.Campaign_ID 
      AND Content_Row_ID = 39200 
      AND rownum<=1) AS Value39200
FROM Source s;

Wiederholen Sie die Unterabfrage für jede additonal Content_Row_ID.

diese in Standard-SQL zu tun, müssen Sie alle unterschiedlichen Werte von Content_Row_ID kennen, und pro eindeutigen Wert eine Verknüpfung tun. Dann brauchen Sie eine Spalte pro eindeutigen Wert von Content_Row_ID.

SELECT CA.Campaign_ID, 
  C1.Content_Value AS "39100",
  C2.Content_Value AS "39200",
  C3.Content_Value AS "39300"
FROM Campaign CA
  LEFT OUTER JOIN Content C1 ON (CA.Campaign_ID = C1.Campaign_ID 
    AND C1.Content_Row_ID = 39100)
  LEFT OUTER JOIN Content C2 ON (CA.Campaign_ID = C2.Campaign_ID 
    AND C2.Content_Row_ID = 39200)
  LEFT OUTER JOIN Content C3 ON (CA.Campaign_ID = C3.Campaign_ID 
    AND C3.Content_Row_ID = 39300);

Da die Anzahl der unterschiedlichen Werte größer wird, diese Abfrage zu teuer wird effizienter ausgeführt werden. Es ist wahrscheinlich einfacher, die Daten zu holen einfacher und formatiert es in PL / SQL oder in Anwendungscode.

Bill Karwin und Anders Eurenius korrekt ist, dass es keine Lösung gibt, die einfach ist, noch gibt es überhaupt eine Lösung, wenn die Anzahl der resultierenden Spaltenwerte nicht im Voraus bekannt ist. Oracle 11g tut es vereinfachen etwas mit der PIVOT-Operator , aber die Spalten müssen noch im Voraus bekannt sein und dass die 10g Kriterien Ihrer Frage nicht erfüllt.

Wenn Sie eine dynamische Anzahl der Spalten müssen, ich glaube nicht, dies kann in Standard-SQL erfolgen, die, ach, mein Wissen übersteigt. Aber es gibt Funktionen von Oracle, die es tun kann. Ich fand einige Ressourcen:

http://www.sqlsnippets.com/en/topic-12200.html

http: //asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:124812348063#41097616566309

Wenn Sie „Oracle, die Complete Reference“ Look für einen Abschnitt mit dem Titel „Turning eine Tabelle auf der Seite“. Dies gibt detaillierte Beispiele und Anleitungen für eine Pivot-Durchführung, obwohl die Ausgabe Ich habe es nicht nennen Dreh.

Ein anderer Begriff für „eine Tabelle Schwenken“ ist Kreuztabelle.

Eine der einfachsten Werkzeuge zum Ausführen von Kreuztabelle zu verwenden ist MS Access. Wenn Sie MS Access, und Sie können eine Tabelle Link aus einer Access-Datenbank in der Quelltabelle etablieren, sind Sie bereits auf halbem Weg.

An diesem Punkt können Sie die „Abfrage-Assistenten“ aufdrehen, und fragen Sie es für Sie eine Kreuztabelle Abfrage zu erstellen. Es ist wirklich so einfach, wie die Beantwortung der Fragen der Assistent fragt. Die unglückliche Seite dieser Lösung ist, dass, wenn Blick auf der resultierende Abfrage in SQL-Ansicht, werden Sie einige SQL sehen, die auf den Access SQL-Dialekt eigentümlich sind, und kann nicht verwendet werden, in der Regel über andere Plattformen.

Sie können auch einige einfache Analyse-Tools von der Oracle-Website herunterladen können, und eines dieser Tools verwenden, um eine Kreuztabelle für Sie durchführen.

Noch einmal, wenn Sie es wirklich in SQL tun wollen, "Oracle, die Complete Reference" soll Ihnen helfen.

Wenn Sie die Anzahl der Spalten nicht wissen vorne bringt nur eine normale SQL-Abfrage zurück und serverseitigen Code verwenden, wie ich hier aufgelistet: Füllen DataGrid- und sQL-Abfrage

Ich habe eine Lösung mit dieser SQL. I Needed, dass die Zeilen die Anzahl der Klassen und die Spalten der Sumary jedes classe Monat sein, so wird die erste Spalte ist die Sumary der Zeile und jeder ohters Spalten sind die Sumary eines jeden Monats, und die letzte Reihe ist die Sumary von kompletten Spalt von Monat zu Monat.

Viel Glück

Select DS.Cla,
Sum(case
when (Extract(year from DS.Data) =:intYear) then DS.PRE
else 0
end) as ToTal,
Sum(case
when (Extract(month from DS.Data) =1) then DS.PRE
else 0
end) as Jan,
Sum(case
when (Extract(month from DS.Data) =2) then DS.PRE
else 0
end) as FEV,
Sum(case
when (Extract(month from DS.Data) =3) then DS.PRE
else 0
end) as MAR,
Sum(case
when (Extract(month from DS.Data) =4) then DS.PRE
else 0
end) as ABR,
Sum(case
when (Extract(month from DS.Data) =5) then DS.PRE
else 0
end) as MAI,
Sum(case
when (Extract(month from DS.Data) =6) then DS.PRE
else 0
end) as JUN,
Sum(case
when (Extract(month from DS.Data) =7) then DS.PRE
else 0
end) as JUL,
Sum(case
when (Extract(month from DS.Data) =8) then DS.PRE
else 0
end) as AGO,
Sum(case
when (Extract(month from DS.Data) =9) then DS.PRE
else 0
end) as SETE,
Sum(case
when (Extract(month from DS.Data) =10) then DS.PRE
else 0
end) as OUT,
Sum(case
when (Extract(month from DS.Data) =11) then DS.PRE
else 0
end) as NOV,
Sum(case
when (Extract(month from DS.Data) =12) then DS.PRE
else 0
end) as DEZ
from Dados DS
Where DS.Cla > 0
And Extract(Year from DS.Data) = :intYear
group by DS.CLA

Union All

Select 0*count(DS.cla),  0*count(DS.cla),
Sum(case
when (Extract(month from DS.Data) =1) then DS.PRE
else 0
end) as JAN,
Sum(case
when (Extract(month from DS.Data) =2) then DS.PRE
else 0
end) as FEV,
Sum(case
when (Extract(month from DS.Data) =3) then DS.PRE
else 0
end) as MAR,
Sum(case
when (Extract(month from DS.Data) =4) then DS.PRE
else 0
end) as ABR,
Sum(case
when (Extract(month from DS.Data) =5) then DS.PRE
else 0
end) as MAI,
Sum(case
when (Extract(month from DS.Data) =6) then DS.PRE
else 0
end) as JUN,
Sum(case
when (Extract(month from DS.Data) =7) then DS.PRE
else 0
end) as JUL,
Sum(case
when (Extract(month from DS.Data) =8) then DS.PRE
else 0
end) as AGO,
Sum(case
when (Extract(month from DS.Data) =9) then DS.PRE
else 0
end) as SETE,
Sum(case
when (Extract(month from DS.Data) =10) then DS.PRE
else 0
end) as OUT,
Sum(case
when (Extract(month from DS.Data) =11) then DS.PRE
else 0
end) as NOV,
Sum(case
when (Extract(month from DS.Data) =12) then DS.PRE
else 0
end) as DEZ
from Dados DS
Where DS.Cla > 0
And Extract(Year from DS.Data) = :intYear
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top