2016-06-20 34 views
0

Ich verwende das folgende Skript, um einige grundlegende Informationen zurückzugeben. das Skript gibt 65 Zeilen (wie erwartet) ...Oracle SQL: Rückgabe Nullwert, wenn kein listagg Ergebnis

select unique 
     trunc(li.cre_dat) cre_date, 
     li.cre_usr, 
     li.catnr, 
     li.av_part_no, 
     li.artist, 
     li.title, 
     li.prodtyp, 
     li.packtyp, 
     nvl(sp.name_for_customer,sp.name) pack_type 
from leos_item li, 
     scm_packtyp sp 
where li.cunr in ('816900','816901','816902') 
and li.item_type = 'FP' 
and li.av_part_no is null 
and trunc(li.cre_dat) >= '01-JAN-2016' 
and li.model_force_creation_idc != 'Y' 
and li.i_status != 'I' 
and li.packtyp = sp.packtyp 

... aber, wenn ich Listagg in meiner wählt, der Bericht liefert nur 55 Zeilen hinzufügen. 10 Zeilen haben kein Listagg-Ergebnis, daher werden die Ergebnisse weggelassen ...

select unique 
     trunc(li.cre_dat) cre_date, 
     li.cre_usr, 
     li.catnr, 
     li.av_part_no, 
     li.artist, 
     li.title, 
     li.prodtyp, 
     li.packtyp, 
     nvl(sp.name_for_customer,sp.name) pack_type, 
     regexp_replace(listagg(nvl(bom.av_part_no,'No'), ', ') 
     within group (order by bom.item_id),'([^,]+)(,\1)+', '\1') masters 
from leos_item li, 
     scm_packtyp sp, 
     TABLE(leos_flatbom_pkg.GetFlatBOM(li.item_id)) bom, 
     leos_item li1 
where li.cunr in ('816900','816901','816902') 
and li.item_type = 'FP' 
and li.av_part_no is null 
and trunc(li.cre_dat) >= '01-JAN-2016' 
and li.model_force_creation_idc != 'Y' 
and li.i_status != 'I' 
and li.packtyp = sp.packtyp 
and bom.item_id = li1.item_id 
and li1.item_type = 'MT' 
group by li.cre_dat, 
     li.cre_usr, 
     li.catnr, 
     li.av_part_no, 
     li.artist, 
     li.title, 
     li.prodtyp, 
     li.packtyp, 
     nvl(sp.name_for_customer,sp.name) 

Aber ich muss auch diese Zeilen sehen. Gibt es eine Möglichkeit, die 10 Zeilen zurückzugeben, in denen kein Listagg-Ergebnis gefunden wurde. Ich habe die folgenden Kombinationen von nullif und nvl ausprobiert, aber ohne Glück;

nullif(regexp_replace(listagg(nvl(bom.av_part_no,'No'), ', ') within group (order by bom.item_id),'([^,]+)(,\1)+', '\1'),'No Master') 

nvl(regexp_replace(listagg(nvl(bom.av_part_no,'No'), ', ') within group (order by bom.item_id),'([^,]+)(,\1)+', '\1'),'No Master') 
+0

können Sie einige Beispieldaten vielleicht ein mit t konstruieren oder eine kleine Tabellendefinition mit einem Post einige Insert-Anweisungen, um Ihr Problem zu zeigen. Ich habe gerade eine kleine Liste mit der HR Mitarbeiter Tabelle versucht und die Nullen wurden zurückgegeben. SELECT department_id, LISTAGG (commission_pct, ',') WITHIN GRUPPE (ORDER BY hire_date, last_name) von Mitarbeitern group by department_id; –

Antwort

1

Das Problem ist nicht mit LISTAGG es ist, dass sie ein innere Verknüpfung zum TABLE Sammlung Ausdruck für leos_flatbom_pkg.GetFlatBOM(li.item_id) durchführen und dass enthält null Zeilen, so dass die übergeordnete Zeile aus den Ergebnissen werden filtriert.

es Ersetzen mit einer korrelierten Unterabfrage etwas wie folgt aus:

select unique 
     trunc(li.cre_dat) cre_date, 
     li.cre_usr, 
     li.catnr, 
     li.av_part_no, 
     li.artist, 
     li.title, 
     li.prodtyp, 
     li.packtyp, 
     nvl(sp.name_for_customer,sp.name) pack_type, 
     (SELECT regexp_replace(listagg(nvl(bom.av_part_no,'No'), ', ') 
        within group (order by bom.item_id),'([^,]+)(,\1)+', '\1') 
     FROM TABLE(leos_flatbom_pkg.GetFlatBOM(li.item_id)) bom 
       INNER JOIN leos_item li1 
       ON (bom.item_id = li1.item_id) 
     WHERE li1.item_type = 'MT' 
     ) masters 
from leos_item li 
     INNER JOIN 
     scm_packtyp sp 
     ON (li.packtyp = sp.packtyp) 
where li.cunr in ('816900','816901','816902') 
and li.item_type = 'FP' 
and li.av_part_no is null 
and li.cre_dat >= DATE '2016-01-01' 
and li.model_force_creation_idc != 'Y' 
and li.i_status != 'I' 

Einige andere Punkte:

  • Bitte ändern Sie die ANSI-Join-Syntax zu verwenden. Die alte Oracle-Komma-Joinsyntax ist schwer zu erkennen, wie die Spalten verbunden sind (insbesondere für äußere Joins), da die Join-Bedingung in der WHERE-Klausel verborgen ist.
  • Verwenden Sie keine Zeichenkettenliterale für Datumsangaben (zB '01 -JAN-2016 '). Oracle führt implizit TO_DATE() mit dem Session-Parameter NLS_DATE_FORMAT als Formatmaske aus. Wenn sich dies ändert, bricht die Abfrage ab (ohne je Ändern des Textes der Anfrage) und es wird mühsam zu debuggen. Schlimmer noch, dies ist ein Session-Parameter, so dass es für einen Benutzer möglich ist, es zu ändern, und dann wird es für alle anderen und nicht für sie funktionieren. Verwenden Sie Datumsliterale (z. B. DATE '2016-01-01') oder rufen Sie explizit TO_DATE() auf und stellen Sie die Formatmaske bereit und korrigieren Sie die Einstellungen NLS.
  • li.cre_dat >= TRUNC(li.cre_dat) also, wenn TRUNC(li.cre_dat) >= DATE '2016-01-01' ist wahr dann li.cre_dat >= DATE '2016-01-01' wird auch wahr sein. Der Widerspruch ist, dass Sie den TRUNC() Anruf beseitigen können.

Sie könnten lösen es auch Ihre zweite Abfrage und zum Umwandeln des TABLE colection Ausdruck unter Verwendung eines sein OUTER JOIN:

from leos_item li 
     scm_packtyp sp, 
     TABLE(leos_flatbom_pkg.GetFlatBOM(li.item_id)) (+) bom, 
     leos_item li1 
where ... 
and li.packtyp = sp.packtyp 
and li1.item_id = bom.item_id (+) 
+0

Alle Punkte verstanden und an Bord genommen. Vielen Dank, funktioniert perfekt! – SMORF

Verwandte Themen