Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   If Klausel im Select o.ä. gesucht (https://www.delphipraxis.net/180783-if-klausel-im-select-o-ae-gesucht.html)

juergen 17. Jun 2014 16:54

Datenbank: Pervasive • Version: 11 • Zugriff über: PDAC

If Klausel im Select o.ä. gesucht
 
Hallo zusammen,

ich suche für folgendes sinnnbindliches SQL-Statement eine Lösung:
Zitat:

select K.Datum, '', LTrim(P.PersNr), P.Name, P.Vorname, K.Saldo, K.Saldo, K.Saldo from Kontenstand as K, Personalstamm as P where
(K.PersId=P.Identifikation) and ((K.Konto='177')or(K.Konto='189')or(K.Konto='194') ) and (((K.Datum) = CURRENT_DATE()-3)) and (K.Saldo <> '')
Es sollen also 3x hintereinander ein K.Saldo angezeigt werden. Dabei muss beim ersten K.Saldo immer dann der Wert stehen wenn das K.Konto = 177 ist, beim zweiten K.Saldo der Wert des Kontos anzeigen, wenn das K.Konto = 189 ist und beim dritten K.Saldo den Wert anzeigen, wenn das K.Konto = 194 ist.

Ich habe schon einiges probiert, z.B. mit Case. Ich bin mir aber nicht sicher ob das überhaupt richtig ist. Ein funktionierendes SQL-Statement habe ich nicht hinbekommen.

Deswegen meine Frage an die erfahrenen:
Wie müsste das Statement aufgesetzt werden?

Vielen Dank schon mal vorab!

EarlyBird 17. Jun 2014 17:06

AW: If Clausel im Select
 
So könnte es eventuell gehen:
(ungetestet)
Code:
select K.Datum,
'',
LTrim(P.PersNr),
P.Name,
P.Vorname,
Case K.Konto = '177' then K.Saldo else NULL END as Saldo177 ,
Case K.Konto = '189' then K.Saldo else NULL END as Saldo189,
Case K.Konto = '194' then K.Saldo else NULL END as Saldo194 
from Kontenstand as K, Personalstamm as P
where (K.PersId=P.Identifikation)
and
((K.Konto='177')or(K.Konto='189')or(K.Konto='194') )
and
(((K.Datum) = CURRENT_DATE()-3)) and (K.Saldo <> '')

mkinzler 17. Jun 2014 17:10

AW: If Clausel im Select
 
Pervasive kennt laut Hilfe auch die IIF() Funktion


SQL-Code:
select
  K.Datum, '', LTrim(P.PersNr), P.Name, P.Vorname, IIf( K.Konto=177, K.Konto, 0) as K.Saldo177, ...
from
  Kontenstand K,
  Personalstamm P
where
(K.PersId=P.Identifikation) and ((K.Konto='177')or(K.Konto='189')or(K.Konto='194') ) and (((K.Datum) = CURRENT_DATE()-3)) and (K.Saldo <> '');
Btw. entweder IF-Klausel oder IF clause aber nicht IF Clausel, denn das ist weder deutsch noch englisch noch denglish!

p80286 17. Jun 2014 17:12

AW: If Clausel im Select
 
Ich würde hierfür 3 Subselects bemühen
Code:
select ...kt177.Saldo,kt189.saldo,kt194..
from ....
       left join (select Konto,Saldo from Kontenstand where Konto=177) kt177...
       left join (select Konto,Saldo from Kontenstand where Konto=189) kt189...
       left join (select Konto,Saldo from Kontenstand where Konto=189) kt194...

usw.
Gruß
K-H

Jumpy 17. Jun 2014 17:20

AW: If Clausel im Select
 
Nur der Vollständgkeit halber: Mit Union müsste es doch auch gehen, oder?

Code:
select K.Datum,'',LTrim(P.PersNr),P.Name,P.Vorname,
K.Saldo as Saldo177 ,
NULL as Saldo189,
NULL as Saldo194 
from Kontenstand as K, Personalstamm as P
where (K.PersId=P.Identifikation)
  and (((K.Datum) = CURRENT_DATE()-3)) and (K.Saldo <> '')
  and (K.Konto='177')

Union All

select K.Datum,'',LTrim(P.PersNr),P.Name,P.Vorname,
NULL as Saldo177 ,
K.Saldo as Saldo189,
NULL as Saldo194 
from Kontenstand as K, Personalstamm as P
where (K.PersId=P.Identifikation)
  and (((K.Datum) = CURRENT_DATE()-3)) and (K.Saldo <> '')
  and (K.Konto='189')

Union All

...

[OT]
Gibt's da eigentlich so tipps, was von der Performance besser ist? Die Anwendung einer Funktion in jedem Datensatz oder einfach nur drei Abfragen mit Union oder Subselects hintereinander?
[/OT]

jobo 17. Jun 2014 20:26

AW: If Clausel im Select
 
Zitat:

Zitat von Jumpy (Beitrag 1262616)
Gibt's da eigentlich so tipps, was von der Performance besser ist? Die Anwendung einer Funktion in jedem Datensatz oder einfach nur drei Abfragen mit Union oder Subselects hintereinander?
[/OT]

Wahrscheinlich eine Frage des Mengengerüsts (Selektivität) und der Indizierung (Index könnte bei einem Kontoschlüssel gegeben sein)
Die einzelnen Unionabfrage erfordern 3 Zugriffe auf die Gesamtmenge oder eben indizierte Zugriffe.
Ein Einzelstatement mit Iif / Case dürfte auch ohne Index ganz gut abschneiden, wenn die Gesamtmenge nicht viel größer ist als die Menge der 3 Konten.
Wenn sich der Optimizer aufgrund Indizierung und Statistiken zu einem Fullscan durchringt, ist es mit Iif / Case ein einmalige Fullscan, bei dem alle 3 Fälle abgefragt werden, mit Union 3 Fullscans für 3 Konten.
So ungefähr.
Die Nutzung der Funktion spielt dabei m.E. kaum eine Rolle (das ist quasi billiges Kopfrechnen für das System) gegenüber den reinen Zugriffskosten (auf Festplatte). Kleine Gesamtmenge/ alles bereits im -hinreichend großen- Buffer oder schnell bzw überhaupt dort rein zu bekommen oder Datenhaltung auf SSD können es wieder anders aussehen lassen. Aber dann spielt es vermutlich so oder so kaum eine Rolle.

juergen 17. Jun 2014 21:29

AW: If Clausel im Select
 
Erst einmal vielen Dank für die Hilfe!:dp:

@EarlyBird
Bei deinem Vorschlag erhalte ich 3 Zeilen, je Konto eine Zeile. Ich benötige aber alles in einer Zeile. Das hatte ich nicht explizit erwähnt, sorry.


@p80286
Das scheint mir gefühlsmäßig der beste Weg zu sein. Allerdings erhalte ich einen Syntax-Fehler:
Code:
select K.Datum,
 '',
 LTrim(P.PersNr),
 P.Name,
 P.Vorname
from Personalstamm as P
outer join (select Konto,Saldo from Kontenstand where Konto=2) kt2
outer join (select Konto,Saldo from Kontenstand where Konto=8) kt8 
outer join (select Konto,Saldo from Kontenstand where Konto=32) kt32
on (K.PersId=P.Identifikation) and
((K.Konto='2')or(K.Konto='8')or(K.Konto='32') ) and (((K.Datum) = CURRENT_DATE()-1)) and (K.Saldo <> ''
Kann jemand das Problem erkennen? Der Fehler kommt nach dem ersten outer.


@mkinzler
Leider kennt mein Pervasive keine IIF() Funktion.

Ps.:
Zitat:

Zitat von mkinzler (Beitrag 1262611)
Btw. entweder IF-Klausel oder IF clause aber nicht IF Clausel, denn das ist weder deutsch noch englisch noch denglish!

Da hast du natürlich Recht. Danke für den Hinweis!:thumb:


@Jumpy
Generell funktioniert das Statement mit Union. Aber auch hier werden 3 Zeilen erzeugt, für jedes Konto eine Zeile.
Eigentlich müsste meine tabellen-Struktur anders sein. Ich müsste die Konten als Spalten haben und nicht als Zeilen.... Aber da kann ich nichts ändern.

Gibt es für meine Anforderung überhaupt eine Lösung?

mkinzler 17. Jun 2014 21:59

AW: If Klausel im Select o.ä. gesucht
 
Dann musst du die Zeilen per Aggregatfunktion zusammenfassen:
SQL-Code:
select K.Datum,
LTrim(P.PersNr),
P.Name,
P.Vorname,
sum(Case K.Konto = '177' then K.Saldo else 0 END) as Saldo177 ,
sum(Case K.Konto = '189' then K.Saldo else 0 END) as Saldo189,
sum(Case K.Konto = '194' then K.Saldo else 0 END) as Saldo194 
from Kontenstand as K, Personalstamm as P
where (K.PersId=P.Identifikation)
and
((K.Konto='177')or(K.Konto='189')or(K.Konto='194') )
and
(((K.Datum) = CURRENT_DATE()-3)) and (K.Saldo <> '')
order by
  K.Datum, P.PersNr, P.Name, P.Vorname;

juergen 17. Jun 2014 22:51

AW: If Klausel im Select o.ä. gesucht
 
Ich musste das für Pervasive anpassen mit when:
Code:
select K.Datum,
LTrim(P.PersNr),
P.Name,
P.Vorname,
sum(Case when K.Konto = '2' then K.Saldo else 0 END) as Saldo2,
sum(Case when K.Konto = '8' then K.Saldo else 0 END) as Saldo8,
sum(Case when K.Konto = '32' then K.Saldo else 0 END) as Saldo32
from Kontenstand as K, Personalstamm as P
where (K.PersId=P.Identifikation)
and
((K.Konto='2')or(K.Konto='8')or(K.Konto='32') )
and
(((K.Datum) = CURRENT_DATE()-1)) and (K.Saldo <> '')
order by
  K.Datum, P.PersNr, P.Name, P.Vorname
Dann erhalte ich aber die folgende Fehlermeldung:
Column invalid. Must be a group by column: Datum in SELECT LIST


Zur Verdeutlichung noch mal mein Problem:

Meine Tabelle "Kontenstamm" hat folgenden Aufbau:

ID..Konto...PersId...Datum.........Saldo
1.....3............100.....20140616.......420
2.....2............4711...20140616........520
3.....8............100.....20140616.......120
4.....32...........4711...20140616........420
...

Mein Ergebnis soll dann so ausschauen:
..Datum...|.EXPR_1..|.EXPR_2...|..Name......|..Vor name....|..Saldo2....|...Saldo8.....|...Saldo32
6/16/2014.|.................|.100............|..Albers. ......|..Albert............|.(Null).........|...12 0............|...(Null).
6/16/2014.|.................|.4711..........|..Albers.. .....|..Albert............|.520............|...(Nu ll).........|...420....



Edit: Wenn ich anstelle order by dann Group by nehme scheint alles zu funktionieren!

@mkinzler, Vielen Dank!


Gute Nacht an Alle!

p80286 18. Jun 2014 11:20

AW: If Clausel im Select
 
Zitat:

Zitat von Jumpy (Beitrag 1262616)
Gibt's da eigentlich so tipps, was von der Performance besser ist? Die Anwendung einer Funktion in jedem Datensatz oder einfach nur drei Abfragen mit Union oder Subselects hintereinander?

Abseits aller Theorie, kommt es wohl darauf an was die Admins mit den DB so treiben.
Meine praktische Erfahrung zeigt Subselects ganz klar vorne. Union(s) liegen weit hinten.
Aber solange ich nicht an den Zehntelsekunden feilen muß.....

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:13 Uhr.

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