Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi left join NULL (https://www.delphipraxis.net/131470-left-join-null.html)

jangbu 25. Mär 2009 11:11

Datenbank: SQL-Server 2000 • Zugriff über: BDE

left join NULL
 
Hallo,

habe folgende abfrage

select a.menge as bestand, b.menge as reserviert, (a.menge - b.menge) as diff
from tab1 a left join tab2 b on (a.name = b.name)

Bekomme auch für alle Artikel (tab1) die Differenz, außer bei den Artikeln wo keine reservierung besteht (kein Datensatz in Tab2), da bekomme ich diff = NULL. Klar da menge - Null = Null

richtig wäre aber:

menge - NULL = menge

Wie bekomme ich das hin?

Danke
jangbu

mkinzler 25. Mär 2009 11:13

Re: left join NULL
 
Nach Null abfragen ( IIF(), CASE..WHEN, NullIF())

nahpets 25. Mär 2009 11:17

Re: left join NULL
 
Hallo,

so sollte es gehen:
SQL-Code:
select
  a.menge as bestand,
  b.menge as reserviert,
  (IsNull(a.menge,0) - IsNull(b.menge,0)) as diff
from tab1 a left
join tab2 b on (a.name = b.name)

jangbu 25. Mär 2009 11:19

Re: left join NULL
 
super Danke!

jangbu

joachimd 27. Mär 2009 09:01

Re: left join NULL
 
Zitat:

Zitat von jangbu
richtig wäre aber:
menge - NULL = menge

Das wäre vielleicht das von Dir gewünschte, nicht aber das richtige Ergebnis. NULL heißt nicht 0, sondern undefiniert und daher MUSS jede Operation, die mit einem NULL-Wert rechnet, ebenso NULL zurückliefern. Klingt komisch, ist aber so;)

Zum Vergleich: Unendlich+1 ist immer noch Unendlich

nahpets 27. Mär 2009 09:33

Re: left join NULL
 
Hallo Joachim,

im Prinzip dürftes Du hier recht haben. Im aktuellen Beispiel sieht mir das aber eher so aus:

Wir haben eine 1:1-Beziehung, bei der man (aus Bequemlichkeit?) auf die 1 hinter dem : verzichtet, sofern dort nur 0 als Wert vorhanden ist. Es dürfte hier wohl korrekter sein, diesen Satz auch dann anzulegen, wenn b.menge = 0 ist.

Für meine Begriffe eine häufig verwendete Unsitte, die die Abfragen unnütz kompilziert machen. Bei "ordentlicher" Ausmodellierung und konsequenter Umsetzung dürfte so manch ein Left Join überflüssig sein und sich oben vorgeschlagene Konstrukte erübrigen.

jangbu 1. Apr 2009 11:20

Re: left join NULL
 
Hab jetzt aber doch noch mal eine Frage dazu:

die Tabelle bestand (a) ist 1:n mit der Tabelle reserviert (b) verknüpft. Es kann also für einen Artikel in (a) mehrer reservierungen in (b) geben.
Für den Fall einer 1:1 Beziehnung klappt folgende Abfrage (auch wenn überhauptkeine Reservierungen bestehen)

SQL-Code:
select
  a.menge as bestand,
  b.menge as reserviert,
  (IsNull(a.menge,0) - IsNull(b.menge,0)) as diff
from tab1 a left
join tab2 b on (a.name = b.name)
Wie bekomme ich jedoch die Differenz - also den verfügbaren Bestand - heraus, wenn es mehrere reservierungen gibt, ich also die "Summe der reservierungen" vom Bestand abziehen muss?
Durch den left join bekomme ich soviele Zeilen zurück wie es reservierungen gibt, brauche aber nur eine, müsste vorher in der rechten tabelle die summe bilden.

jangbu

[edit=mkinzler]SQL-Tag eingefügt Mfg, mkinzler[/edit]

p80286 1. Apr 2009 13:05

Re: left join NULL
 
Hallo jangbu,

Zitat:

...reservierungen gibt, brauche aber nur eine, müsste vorher in der rechten tabelle die summe bilden.
so könnte mann es machen. Wenn ich mich richtig erinnere hast Du beim M$-SQL-Server die Möglichkeit eine temporäre Tabelle anzulegen, die würde ich dann für die Abfage nutzen. Eine andere Möglichkeit wäre ein entsprechender View oder ggf. eine Funktion die Dir die Daten zurückgibt.
In meiner Erinnerung sind die MS-Views aber elend langsam.

warum gibt es eigentlich mehrere einträge mit Reservierung?

Gruß
K-H

nahpets 1. Apr 2009 15:56

Re: left join NULL
 
Hallo,

mal ein nicht getesteter Versuch:

SQL-Code:
select
  Bestand,
  Reserviert,
  Bestand - Reserviert As Diff
from
(
  select
    a.Name,
    Max(IsNull(a.Menge,0)) As Bestand, /* Sollte immer der gleiche Wert sein. */
    Sum(IsNull(b.Menge,0)) As Reserviert
  from tab1 a left
  join tab2 b on (a.Name = b.Name)
  Group By a.Name
) intern

joachimd 2. Apr 2009 08:40

Re: left join NULL
 
müsste auch über eine einfache Gruppierung gehen:

SQL-Code:
select
  a.Bestand,
  b.Reserviert,
  a.Bestand - ifnull(b.Reserviert,0) As Diff
from
tab1 a left outer join
(
  select
    Name,
    Sum(Menge) As Reserviert -- Aggregatfunktionen ignorieren NULL-Werte
    from tab2
    Group By 1
) b
on a.name=b.name
Je nach DBMS ist diese Variante schneller.
Übrigens: Verzichte bitte auf die Verknüpfung über den Namen und nimm einen nichtssagenden Schlüssel (Primary Key, Autoinc -bäh- oder GUID). Einmal den Namen falsch geschrieben, findest Du die richtige Menge nicht mehr.
Und noch eine ganz exotische Geschichte, die eventuell noch mehr Performance bringen kann - und vor allem auch hilft, falls Du mehrere Bestände des gleichen Artikels in Tab1 hast:

SQL-Code:
select
  name,
  sum(bestand) as bestand,
  sum(reserviert) as reserviert,
  sum(bestand)-sum(reserviert) as diff
from
(
  select name, bestand, 0 as reserviert from tab1
  union
  select name, 0 as bestand, reserviert from tab2
)
group by 1


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:15 Uhr.
Seite 1 von 2  1 2      

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