Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Syntaxanfrage (https://www.delphipraxis.net/189972-syntaxanfrage.html)

p80286 15. Aug 2016 12:53

Datenbank: oracle • Version: 11 • Zugriff über: egal

Syntaxanfrage
 
Hallo zusammen,
nac einiger Zeit muß ich mich um eine Abfrage kümmern, deren Details ich nicht ganz verstehe, bzw. Ich schaff es nicht das richtige Stichwort für die Suche in Oracle zu finden
SQL-Code:

with bucnt as
(
  select count(cases.casekey) cnt,substr(v_mk.busunit,1,1) bu
  from cases join v_event on (cases.casekey=v_event.casekey and V_Event.Eventcode='IDR')
        left join v_mk on (cases.casekey=v_mk.casekey)
  where 1=1
    and Cases.CaseTypeKey=5 -- ErfiMeldung
    and v_event.Eventdate >= add_months(
                           to_date(to_char(trunc(sysdate),'YYYYMM')||'01','YYYYMMDD'),-1)
    and v_event.Eventdate< to_date(to_char(trunc(sysdate),'YYYYMM')||'01','YYYYMMDD')
    and cases.casereference like 'DS%'
  group by substr(v_mk.busunit,1,1)
)
select max(a_c) DEM_SummeA
      ,max(k_c) DEM_SummeK
      ,max(w_c) DEM_SummeW
      ,max(misc_c) DEM_Summe_
      ,max(a_c)+max(k_c)+max(w_c)+max(misc_c) DEM_Summe
from
  (select 0 a_c, 0 k_c,0 w_c,0 misc_c from dual     ------- einmal Basisdaten bitte
   union
   select a_c,k_c,w_c,misc_c
   from
     (select nvl(bucnt.cnt,0) a_c,0 w_c, 0 Misc_c from bucnt where bucnt.bu='A' )
     full outer join
     (select nvl(cnt,0) k_c from bucnt where bucnt.bu='B' ) on 1=1
   union
   select a_c,k_c,w_c,misc_c
   from
     (select nvl(cnt,0) w_c,0 k_c,0 a_c from bucnt where bucnt.bu='L' )
     full outer join
     (select cnt misc_c from bucnt where ((bucnt.bu<>'A' and bucnt.bu<>'B' and bucnt.bu<>'L') or bucnt.bu is null)
     ) on 1=1
  )
das Ergebnis des ersten selects ist ein 4-Zeiler, der mit den beiden full outer joins zu einem Dreizeiler mit 4 Spalten wird. Und genau da steh ich mir selbst auf der Leitung. Warum funktioniert das so und nicht anders.

Gruß
K-H

DeddyH 15. Aug 2016 13:30

AW: Syntaxanfrage
 
Klingt nach Pivot (Kreuztabelle).

nahpets 15. Aug 2016 13:58

AW: Syntaxanfrage
 
Wenn ich die Aufgabenstellung richtig verstehe, geht es doch darum, mehrere nacheinander ermittelte Werte aus einer Tabelle im Ergebnis nebeneinander darzustellen.

Insgesamt erscheint mir das Statement sehr komplex, so dass ich nicht nachvollziehen kann, warum das so und nicht anders gelöst wurde.

Als erstes würd' ich mal diese beiden Zeilen wegwerfen, sie sind überflüssig:
SQL-Code:
select 0 a_c, 0 k_c,0 w_c,0 misc_c from dual ------- einmal Basisdaten bitte
union
Durch das Max() gehen die Werte verloren, es sei denn, im "Rest" kämen nur negative Werte vor, dann blieben die Nullen als Maximalwerte übrig.
Es könnte eventuell auch sein, dass das erforderlich ist, sofern der "Rest" eine leere Ergebnismenge liefert.
Wäre das im Rahmen des Möglichen?
(Edit: Aber das müsste das NVL doch eigentlich verhindern? Oder?)

Den Teil, in dem die Maximalwerte ermittelt werden, würd' ich so schreiben:
SQL-Code:
select max(a_c) DEM_SummeA
      ,max(k_c) DEM_SummeK
      ,max(w_c) DEM_SummeW
      ,max(misc_c) DEM_Summe_
      ,max(a_c)+max(k_c)+max(w_c)+max(misc_c) DEM_Summe
from
(
  select nvl(cnt,0) a_c, 0 w_c,         0 k_c,         0 Misc_c  from bucnt where bu='A'
  union all
  select 0                a_c, 0 w_c,         nvl(cnt,0) k_c, 0 Misc_c  from bucnt where bu='B'
  union all
  select 0                a_c, nvl(cnt,0) w_c, 0          k_c, 0 Misc_c  from bucnt where bu='L'
  union all
  select 0                a_c, 0 w_c,         0          k_c, cnt misc_c from bucnt where ((bu not in ('A','B','L')) or bu is null
)
(Hoffentlich hab' ich da jetzt nix wesentliches übersehen.)

Nachtrag:

Mir fällt gerade auf, dass das "full outer join" ja zu einem kartesischen Produkt führt. Man bekommt also in der Ergebnismenge alle Spalten aller Selects, ohne sie einzeln im Statement "aufführen" zu müssen.
Da schreib' ich lieber ein bisserl mehr und hab' es insgesamt etwas übersichtlicher. Aber das ist dann wohl auch etwas "Geschmacksfrage" ;-)

jobo 15. Aug 2016 14:38

AW: Syntaxanfrage
 
"t1 full outer join t2 on 1=1" ist mit dieser Bedingung das Kreuzprodukt
wäre sinnvoller / verständlicher so zu schreiben:
"t1 cross join t2" und liefert das kartesische Produkt.

Früher (als oracle noch keine joins konnte) hätte man es so geschrieben (geht immer noch)
"[select columns from ]t1, t2" (ohne where condition)

Und ja, hier kann es nur darum gehen ein paar Zahlen nebeneinander zu bekommen. Würde man evtl. heute mit "Pivot" machen.

Die Logik, warum paarweise die CNT pivotisiert werden, finde ich so auch nicht zu verstehen.

Vielleicht ginge auch sowas in der Art, weil lauter Summen aus 0 und einem Wert dann auch nur den gleichen Wert ergeben und das Statement vielleicht eine Mischung aus Unwissenheit, früher standen da noch andere Werte-die wir nich mehr brauchen- und Migration aus einer anderen DB ist.

Code:
select a_c,k_c,w_c,misc_c from
(Select max(..cnt) as a_c from bucnt where having bu='A' group by ... ) a,
(Select max(..cnt) as k_c from bucnt where having bu='B' group by ... ) b,
(Select max(..cnt) as w_c from bucnt where having bu='L' group by ... ) c,
(Select max(..cnt) as misc_c from bucnt where having bu!='L' and ... group by ... ) d
(mit 'ohne' old school cross join kriterien)

p80286 15. Aug 2016 18:21

AW: Syntaxanfrage
 
Vielen Dank für die vielen Antworten.
Zunächst einmal, PIVOT war ein gutes Stichwort ich hab eine der vorhandenen Abfragen mal umgestellt, jetzt ist es etwas übersichtlicher:
SQL-Code:
with bucnt as
(
select count(v_lebfam.casekey) cnt
,decode(substr(v_mk.Busunit,1,1),'T','A','L','L','B','B','A','A','sonstige') bu
from v_lebfam,v_MK
 ,(select distinct familykey
from cases join caseevent on (cases.casekey=caseevent.casekey and eventkey=25) --Grant
where cases.casetypekey=1
  and cases.casereference not like 'TE%'
  and cases.casereference like 'PT%'
  and not exists(select * from caseevent e where e.casekey=cases.casekey and e.eventkey=30) -- ABD
  and not exists(select * from caseevent e where e.casekey=cases.casekey and e.eventkey=50 and e.eventdate is not null) -- ABD
) erteilt
where v_lebfam.casekey=v_MK.casekey(+)
  and v_lebfam.casekey=erteilt.familykey
group by decode(substr(v_mk.Busunit,1,1),'T','A','L','L','B','B','A','A','sonstige')
)
select 'ErfMeld' as Topic,A,B,L,Sonstige from bucnt pivot(sum(cnt) for (bu) in ('A' as A,'B' as B,'L' as L,'sonstige' as Sonstige))
(Ist etwas anders als die erste Abfrage, aber das Prinzip ist das gleiche)

@nahpets & @jobo
Es kann vorkommen, daß es zu einem oder mehreren BU keinen Wert gibt. Wenn die entsprechende Zeile dann nicht vorhanden ist, gibt es immer noch die Basisdaten, die bei max(spalte) auf jeden Fall die 0 liefern.

Mal schauen was ich aus den beiden Möglichkeiten mache, da ich auch gerne "Topic" im ersten Select unterbringen würde.

Vielen Dank nochmals
K-H

nahpets 15. Aug 2016 19:36

AW: Syntaxanfrage
 
SQL-Code:
and cases.casereference not like 'TE%'
and cases.casereference like 'PT%'
Das versteh' ich nicht, wenn etwas like PT% ist, ist es doch zwingend nicht like TE%.

Kann man sich da die erste Zeile nicht sparen?

p80286 15. Aug 2016 22:44

AW: Syntaxanfrage
 
Korrekt, das ist noch ein Überbleibsel aus der Entwicklung.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf