Kein Ergebnis bei Abfrage mit Unterabfragen

Hallo,

vielleicht kann mir bitte jemand weiterhelfen. Ich möchte aus einer Tabelle einzelne Zeilen als Spalte darstellen lassen und bastele mir folgende SQL-Anweisung mit Java zusammen.

SELECT "0002,0000", "0008,0020", "0008,0021"
FROM 
(SELECT value AS "0002,0000", sopinstanceuid 
    FROM dcmtag 
    WHERE tag = '0002,0000' 
    AND sopinstanceuid 
        IN ('1.3.51.0.7.2545223877.51878.5447.48939.44644.10011.28045', ...)) AS "tagtable0002,0000", 
(SELECT value AS "0008,0020", sopinstanceuid 
    FROM dcmtag 
    WHERE tag = '0008,0020' 
    AND sopinstanceuid 
        IN ('1.3.51.0.7.2545223877.51878.5447.48939.44644.10011.28045', ...)) AS "tagtable0008,0020", 
(SELECT value AS "0008,0021", sopinstanceuid 
    FROM dcmtag 
    WHERE tag = '0008,0021' 
    AND sopinstanceuid 
        IN ('1.3.51.0.7.2545223877.51878.5447.48939.44644.10011.28045', ...)) AS "tagtable0008,0021", 
WHERE "tagtable0002,0000".sopinstanceuid = "tagtable0008,0020".sopinstanceuid 
AND "tagtable0008,0020".sopinstanceuid = "tagtable0008,0021".sopinstanceuid

Die Abfrage funktioniert einwandfrei, wenn alle Unterabfragen Ergebnisse zurückliefern. Liefert aber eine Unterabfrage kein Ergebnis, bekomme ich über die ganze Abfrage auch kein Ergebniszeilen. Hat jemand eine Idee, wie ich das Ergebnis der anderen Unterabfragen trotzdem ausgeben kann???

Schon mal Danke für jede Hilfe!

Liegt wohl an Deiner WHERE-Condition. Kurzer Nachbau:

test=# select * from (select 'a', 1 as "eins" union select 'b', 2) bla1, (select 'a', null as "zwei" union select 'b', 2) bla2;
 ?column? | eins | ?column? | zwei
----------+------+----------+------
 a        |    1 | a        |
 a        |    1 | b        |    2
 b        |    2 | a        |
 b        |    2 | b        |    2
(4 Zeilen)

Zeit: 0,369 ms
test=*# select * from (select 'a', 1 as "eins" union select 'b', 2) bla1, (select 'a', null as "zwei" union select 'b', 2) bla2 where eins = zwei;
 ?column? | eins | ?column? | zwei
----------+------+----------+------
 b        |    2 | b        |    2
(1 Zeile)

Zeit: 20,770 ms
test=*# select * from (select 'a', 1 as "eins" union select 'b', 1) bla1, (select 'a', null as "zwei" union select 'b', 2) bla2 where eins = zwei;
 ?column? | eins | ?column? | zwei
----------+------+----------+------
(0 Zeilen)

Wie man aus Zeilen Spalten machen kann habe ich diese Woche, glaube ich, schon 2 mal hier gezeigt. Und wir haben erst Mittwoch …

Andreas

Hallo,

versteh ich leider trotzdem nicht und die anderen Beiträge, die um das gleiche Thema gehen sollen find ich auch nicht …
An welcher WHERE-Condition soll dass denn liegen? Versteh das nicht! Sobald ich bei jeder Unterabfrage eine Ergebnismenge bekomm, funktioniert das ja wunderbar …!

Kannst du mir bitte nochmals Nachhilfe geben und ggfs. die betreffenden Beiträge zeigen?

Danke!

Deine Tabelle dcmtag enthält ja, vereinfacht, dies:

test=*# select * from elephant ;
 value | id
-------+----
   100 |  1
   200 |  2
   300 |  3
   400 |  4
(4 Zeilen)

Wenn ich in Deine Abfrage so darauf anwende, aber aus der ersten Zeile ein “select *” mache und die letzten 2 Zeilen weglasse (also bei Dir diese Zeilen:

WHERE “tagtable0002,0000”.sopinstanceuid = “tagtable0008,0020”.sopinstanceuid
AND “tagtable0008,0020”.sopinstanceuid = “tagtable0008,0021”.sopinstanceuid


dann erhalte ich ich dies:

test=*# select * from (select value as col1, id from elephant where id=1) as tab1, (select value as col2, id from elephant where id=2) as tab2, (select value as col3, id from elephant where id=3) as tab3;
 col1 | id | col2 | id | col3 | id
------+----+------+----+------+----
  100 |  1 |  200 |  2 |  300 |  3
(1 Zeile)

Was würde denn Deine Abfrage, nach meinem Schema verändert, bringen? Laß mich raten: eine der “sopinstanceuid” - Spalten enthält NULL, und Du hättest (vermutlich) mehrere Zeilen.



Lösung:

test=*# select sum(case when id=1 then value else NULL end) as col1, sum(case when id=2 then value else NULL end) as col2, sum(case when id=5 then value else NULL end) as col5 from elephant;
 col1 | col2 | col5
------+------+------
  100 |  200 |
(1 Zeile)

Und so eine Geschichte mit CASE WHEN … ELSE … END habe ich schon nun zum 3. Mal diese Woche gezeigt.

Andreas

Schreib halt endlich mal ein paar FAQ-Einträge, Xandrian freut sich bestimmt!

Dann musst du das nicht immer neu erklären sondern kannst gleich drauf verweisen :wink:

Ich bin mir gar nicht sicher, dort Schreibrechte zu haben …


Andreas

Hab ich nicht, also meine FAQ mal bitte an die richtige Stelle verschieben.


Andreas

erledischt…

Hallo,

das hab ich verstanden! Aber ich kann die Lösung nicht auf mein Problem anwenden. Die Tabellenstruktur sieht stark vereinfacht wie folgt aus:

 sopinstanceuid |      tag     | value
----------------+-------------+------
   123          |  0008,0008   | test1
   123          |  0008,0021   | test2
   123          |  0010,0010   | test3
   123          |  0018,0090   | test4

   456          |  0008,0008   | test11
   456          |  0008,0021   | test22
   456          |  0010,0010   | test33

   789          |  0008,0008   | test111
   789          |  0008,0021   | test222
   789          |  0010,0010   | test333
   789          |  0018,0090   | test444

Die sopinstanceuid fasst sozusagen die tags mit value zu einer logischen Einheit zusammen. Man könnte zwar bei diesem einfachen Beispiel auf die Idee kommen, daraus zwei Tabellen zu machen, praktisch ist aber das unmöglich …
Man beachte, dass bei sopinstanceuid 456 der tag 0018,0090 fehlt!

Das erwartete Ergbnis sieht dann folgendermaßen aus:

0008,0008  |  0008,0021  | 0010,0010  | 0018,0090
 ----------+-------------+------------+----------+
   test1    |    test2   |    test3   |   test4
   test11   |    test22  |    test33  |    
   test111  |    test222 |    test333 |   test444

Die WHERE-CLAUSE sorgt dafür, dass die values in einer Zeile stehen. Ansonsten würde das ein cross-Join werden …

Die Abfrage von oben erspar ich mir an dieser Stelle! Wie gesagt funktioniert das einwandfrei, wenn alle Unterabfragen Ergebnisse zurückliefern. Es muss doch eine Möglichkeit geben, trotzdem immer alle Ergebnisse auszugeben, auch wenn eine Unterabfrage nichts zurückgibt!

Schon mal Danke für deine/eure Hilfe!



http://www.pg-forum.de/h-ufig-gestellte-fragen-faq/4067-faq-zeilen-zu-spalten.html

Andreas

Hallo nochmals,

ich hab das Beispiel gestern zig mal versucht umzusetzen, bin aber leider gescheitert. Hab allerdings die Funktion crosstab für mein Problemchen entdeckt. Allerdings hakt die ganze Sache noch an den Anzahl Spalten. Meine Query:

SELECT * FROM crosstab('SELECT sopinstanceuid,  tag, value from dcmtag WHERE 
tag = ''0000,0903''  AND sopinstanceuid IN (''1.3.51.0.7.2545223877.51878.5447.48939.44644.10011.28045'')  
OR tag = ''0008,0032''  AND sopinstanceuid IN (''1.3.51.0.7.2545223877.51878.5447.48939.44644.10011.28045'')   
OR tag = ''0008,0068''  AND sopinstanceuid IN (''1.3.51.0.7.2545223877.51878.5447.48939.44644.10011.28045'')  
OR tag = ''0008,1030''  AND sopinstanceuid IN (''1.3.51.0.7.2545223877.51878.5447.48939.44644.10011.28045'') ',
'SELECT DISTINCT tag from dcmtag 
    WHERE tag = ''0000,0903'' 
       OR tag = ''0008,0032'' 
       OR tag = ''0008,0068'' 
       OR tag = ''0008,1030'' 
    ORDER BY tag')
AS ct(   "Error ID" text, "Acquisition Time" text, "Presentation Intent Type" text, "Study Description" text)

Ergebnis ist in diesem Beispiel eine vierspaltige Tabelle mit den Spaltennamen “Error ID”, “Acquisition Time”, “Presentation Intent Type”, “Study Description”.
Beim crosstab enthält doch die erste Spalte die sog. row_id (bei mir die sog. sopinstanceuid), die er mir in die Spalte “Error ID” schreibt und falsch ist. Füge ich der AS-Clause noch einen Parameter row_id hinzu sagt er mir:
Query-specified return tuple has 5 columns but crosstab returns 4

Ich starre schon stundenlang auf das Beispiel in der Doku und versuch den Fehler zu finden. Darin entspricht die “Kategorie-Abfrage”, also die zweite SELECT DISTINCT auch nicht der Anzahl der Parameter in der AS-Clause…

Aus der Doku:

SELECT * FROM crosstab
(
  'SELECT rowid, rowdt, attribute, val FROM cth ORDER BY 1',
  'SELECT DISTINCT attribute FROM cth ORDER BY 1'
)
AS
(
       rowid text,
       rowdt timestamp,
       temperature int4,
       test_result text,
       test_startdate timestamp,
       volts float8
);

Bin ja schon kurz vor dem verzweifeln und weiß nicht mehr weiter!

Schon mal DANKE für jede Hilfe!




test=*# select * from elephant ;
 sopinstanceuid |    tag    |  value
----------------+-----------+---------
 123            | 0008,0008 | test1
 123            | 0008,0021 | test2
 123            | 0010,0010 | test3
 123            | 0018,0090 | test4
 456            | 0008,0008 | test11
 456            | 0008,0021 | test22
 456            | 0010,0010 | test33
 789            | 0008,0008 | test111
 789            | 0008,0021 | test222
 789            | 0010,0010 | test333
 789            | 0018,0090 | test444
(11 rows)

test=*# select sopinstanceuid, array_to_string(array_agg(case when tag='0008,0008' then value else null end),',') as "0008,0008", array_to_string(array_agg(case when tag='0008,0021' then value else null end),',') as "0008,0021", array_to_string(array_agg(case when tag='0010,0010' then value else null end),',') as "0010,0010", array_to_string(array_agg(case when tag='0018,0090' then value else null end),',') as "0018,0090" from elephant group by 1 order by 1;
 sopinstanceuid | 0008,0008 | 0008,0021 | 0010,0010 | 0018,0090
----------------+-----------+-----------+-----------+-----------
 123            | test1     | test2     | test3     | test4
 456            | test11    | test22    | test33    |
 789            | test111   | test222   | test333   | test444
(3 rows)

Andreas

… endlich funktioniert es! Vielen DANK!!!

Jetzt möcht ich das auch verstehen … hast du noch kurz Zeit :wink:

Ich nehm mir mal die Zeile:

array_to_string(array_agg(case when tag='0008,0008' then value else null end),',') as "0008,0008",

Die Funktion array_agg macht doch aus der Ergebnismenge ein Array. array_to_string macht aus dem Array einen String mit Komma als Delimiter. Wie kommt es, dass der Inhalt des Strings mit Komma untereinander in der Tabelle steht?

Ich hab ja in meine erste Abfrage mit den SELECT … AS und in der mit crosstab viel Zeit investiert und dennoch hat es nicht funktioniert. Kannst du mir auch sagen wieso?

Bin auch dafür sehr dankbar :slight_smile:

Ich hatte erst:

test=*# select array_to_string(array_agg(case when tag='0008,0008' then value else null end),',') as "0008,0008", array_to_string(array_agg(case when tag='0008,0021' then value else null end),',') as "0008,0021", array_to_string(array_agg(case when tag='0010,0010' then value else null end),',') as "0010,0010", array_to_string(array_agg(case when tag='0018,0090' then value else null end),',') as "0018,0090" from elephant;
      0008,0008       |      0008,0021       |      0010,0010       |   0018,0090
----------------------+----------------------+----------------------+---------------
 test1,test11,test111 | test2,test22,test222 | test3,test33,test333 | test4,test444
(1 row)

Was aber nicht das ist, was Du wolltest. Also habe ich noch die Dingens-Id-Spalte dazugenommen und nach dieser gruppiert.

Andreas

Nochmals vielen Dank!!!