SQL Query gesucht
Hauke
- datenbank
0 Rouven0 Hauke0 Ilja0 Klaus Mock0 Ilja
0 King^Lully
Hallo Leute,
das Thema sagt eigentlich schon alles. Hier ist meine Datenbankstruktur von den 2 Tabellen auf die es ankommt.
Meine 2 Tabellen heißen:
BETREIBER; UNTERNEHMEN
Die Tabelle Betreiber sieht wie folgt aus
BETREIBER | Kennzahl | Netz | KA | Strom | Wasser
---------------------------------------------------------------
| 100100 | 2 | 4 | 3 | 7
| 100200 | 2 | 6 | 7 | 3
UNTERNEHMEN | Ident | Name
--------------------------------
| 1 | ICH AG
| 2 | DU AG
| 3 | ER AG
| 4 | SIE AG
| 5 | ES AG
| 6 | WIR AG
| 7 | IHR AG
Nun möchte ich eine Anfrage machen, in der ich zu einer Kennzahl von BETREIBER alls 4 Namen der Unternehmen anhand der Ident sehen kann, also sollte die Result Tabelle so aussehen:
RESULT | Kennzahl | Netz | KA | Strom | Wasser
--------------------------------------------------------------------
| 100100 | DU AG | SIE AG | ER AG | IHR AG
Für ein Feld ist es ja relativ einfach:
SELECT Name from UNTERNEHMEN where ident=(select netz from BETREIBER where kennzahl=100100);
Nur das müsste ich jetzt irgendwie staffeln. Gibt es da eine Möglichkeit? Sollte am besten OHNE Views gemacht werden
Ich danke schonmal,
Hauke
Hello,
vermutlich kommst du um einen vierfachen Join (siehe SELFHTML: Datenbanken) nicht herum, in etwa so:
SELECT betreiber.kennzahl, u_netz.name AS Netz, u_ka.name AS KA, u_strom.name AS Strom, u_wasser.name AS Wasser
FROM betreiber
LEFT JOIN unternehmen AS u_netz
ON betreiber.netz = u_netz.ident
LEFT JOIN unternehmen AS u_ka
ON betreiber.ka = u_ka.ident
LEFT JOIN unternehmen AS u_strom
ON betreiber.strom = u_strom.ident
LEFT JOIN unternehmen AS u_wasser
ON betreiber.wasser = u_wasser.ident
WHERE betreiber.kennzahl = 100100
Der vierfach Join ist nicht sonderlich effizient, aber in Anbetracht der Datenstruktur fällt mir gerade nichts anderes ein. Ein einfacher Join kann immer nur einen Betreiber suchen, nicht alle 4 auf einmal.
MfG
Rouven
Der vierfach Join ist nicht sonderlich effizient, aber in Anbetracht der Datenstruktur fällt mir gerade nichts anderes ein.
Er könnte vier Abfragen per UNION-Operator zusammenfassen und dann mit einem einzigen JOIN kommen.
Übrigens sollte auch der vierfache JOIN auf ein und dieselbe Tabelle brauchbar effizient sein.
yo,
Er könnte vier Abfragen per UNION-Operator zusammenfassen und dann mit einem einzigen JOIN kommen.
wenn dann UNION ALL und nicht UNION und zum anderen sollte es in der summe auch wieder vier joins sein.
Ilja
Er könnte vier Abfragen per UNION-Operator zusammenfassen und dann mit einem einzigen JOIN kommen.
wenn dann UNION ALL und nicht UNION und zum anderen sollte es in der summe auch wieder vier joins sein.
UNION reicht schon, wenn man die vier Datensatzmengen verbinden will, beachte, dass ein neues Feld ohnehin erforderlich ist für die JOIN-Kennung (welche den Typ beschreibt, vier unterschiedliche JOINs sind ja möglich).
Und wenn diese Vereinigungsmenge dann erst geJOINt wird, dann hat man nur einen JOIN.
(Sollten weitere Widersprüche kommen, dann werden wir hier den SQL-Code bereitstellen. Also bitte versuchen King Lullies Aufwand gering zu halten. Wir sind ja hier kostenfrei, privat und billig.)
yo,
UNION reicht schon,
du scheinst a) nicht zu erkennen, dass es beim dem UNION nicht darum geht, ob es reicht, sondern dass es zuviel ist und das potential trägt falsche ergebnisse zu liefern.
wenn man die vier Datensatzmengen verbinden will, beachte, dass ein neues Feld ohnehin erforderlich ist für die JOIN-Kennung (welche den Typ beschreibt, vier unterschiedliche JOINs sind ja möglich).
Und b) sich der UNION immer nur auf spalten bezieht, die ausgegeben werden, haben also mit den join bedinungen an sich nichts zu tun und sind somit überhaupt nicht erforderlich.
Und wenn diese Vereinigungsmenge dann erst geJOINt wird, dann hat man nur einen JOIN.
der UNION joint nichts, sondern das machen die einzelnen inner joins, von deren du bei dieser lösung vier brauchst.
Ilja
Also, hier eine profikorrekte Lösung mit nur einem JOIN, nur einer Unterabfrage und mit UNION ohne ALL.
SELECT
Betreiber_GUID,
Betreiber_Unternehmen_Kennung,
Unternehmen_GUID,
Unternehmen_Name
FROM
(
SELECT
Betreiber_GUID,
Betreiber_Netz_Unternehmen_GUID AS Betreiber_Unternehmen_GUID,
'Netz' AS Betreiber_Unternehmen_Kennung
FROM
Betreiber
UNION SELECT
Betreiber_GUID,
Betreiber_Ka_Unternehmen_GUID AS Betreiber_Unternehmen_GUID,
'Ka' AS Betreiber_Unternehmen_Kennung
FROM
Betreiber
UNION SELECT
Betreiber_GUID,
Betreiber_Strom_Unternehmen_GUID AS Betreiber_Unternehmen_GUID,
'Strom' AS Betreiber_Unternehmen_Kennung
FROM
Betreiber
UNION SELECT
Betreiber_GUID,
Betreiber_Wasser_Unternehmen_GUID AS Betreiber_Unternehmen_GUID,
'Wasser' AS Betreiber_Unternehmen_Kennung
FROM
Betreiber
) Temp
INNER JOIN
Unternehmen ON (Unternehmen_GUID = Betreiber_Unternehmen_GUID)
ORDER BY
Betreiber_GUID ASC,
Betreiber_Unternehmen_Kennung ASC
Unterstelltes Tabellendesign:
CREATE TABLE [Betreiber] (
[Betreiber_GUID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Betreiber_Betreiber_GUID] DEFAULT (newid()),
[Betreiber_Netz_Unternehmen_GUID] [uniqueidentifier] NOT NULL ,
[Betreiber_Ka_Unternehmen_GUID] [uniqueidentifier] NOT NULL ,
[Betreiber_Strom_Unternehmen_GUID] [uniqueidentifier] NOT NULL ,
[Betreiber_Wasser_Unternehmen_GUID] [uniqueidentifier] NOT NULL ,
CONSTRAINT [PK_Betreiber] PRIMARY KEY CLUSTERED
(
[Betreiber_GUID]
) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [Unternehmen] (
[Unternehmen_GUID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_Unternehmen_Unternehmen_GUID] DEFAULT (newid()),
[Unternehmen_Name] [nvarchar] (50) COLLATE Latin1_General_CI_AS NOT NULL ,
CONSTRAINT [PK_Unternehmen] PRIMARY KEY CLUSTERED
(
[Unternehmen_GUID]
) ON [PRIMARY]
) ON [PRIMARY]
"Designt for" MS SQL Server, sollte/könnte in abgewandelter Form auch auf MySQL laufen (uniqueidentifier durch int ersetzen).
yo,
Also, hier eine profikorrekte Lösung mit nur einem JOIN, nur einer Unterabfrage und mit UNION ohne ALL.
dann schauen wir doch mal, wie das ein profi macht.
a) war vorher nie die rede davon, dass du es in eine unterabfrage einbauen willst, sondern wir sprachen von joins und unions. wenn man die abfrage mit unterabfragen ganz ohne joins lösen kann, dann ist es wohl keine kunst unterabfragen in kombination mit union und nur einem join zu bilden.
b) fehlt mir die einschränkung nach den betreiber mit der kennzahl=100100
c) bekommst du nicht nur einen datensatz wie gefordert in der ergebnismenge sondern mehrere. in dessen folge würde sich dann auch das order by ersparen
d) macht es keinen sinn, bei union alias namen in allen abfragen mit anzugeben, das dbms nimmt sowieso nur die spaltenbezeichner aus der ersten abfrage.
e) habe ich dich bereits darauf hingewiesen, dass der union überflüssig ist und man hier besser einen union all einsetzt. ein union versucht immer doppelte werte der unionmenge zu filtern. das ist hier gar nicht gewollt und kostest somit unnütze performance und birgt die potentiale gefahr, dass gewünschte ergebnisse nicht in der ergebnismenge auftauchen.
-- ab hier beziehe ich mich auf deinen anderen post
f) ich starke zweifel daran habe, das meine abfrage mit den unterabfragen nicht performant sein soll, im gegenteil würde es mich wundern, wäre sie nicht die schnellste.
g) wenn du schon syntaktische fehler findest, sie dann auch beim namen nennst und nicht irgendwelche behauptungen in dem raum stellst.
Ilja
a) war vorher nie die rede davon, dass du es in eine unterabfrage einbauen willst, sondern wir sprachen von joins und unions. wenn man die abfrage mit unterabfragen ganz ohne joins lösen kann, dann ist es wohl keine kunst unterabfragen in kombination mit union und nur einem join zu bilden.
Bezogen uns auf https://forum.selfhtml.org/?t=147605&m=957427 - der Fragesteller störte sich offensichtlich am vierfachen SelfJOIN.
b) fehlt mir die einschränkung nach den betreiber mit der kennzahl=100100
Keine Ahnung, wars wirklich angefordert? Falls ja, dann kann ja Deine WHERE-Klausel benutzt werden und wir haben schon ein Identifikationssystem.
c) bekommst du nicht nur einen datensatz wie gefordert in der ergebnismenge sondern mehrere. in dessen folge würde sich dann auch das order by ersparen
Du wiederholst Dich, wir lieferten ahlt die "Komplettlösung".
d) macht es keinen sinn, bei union alias namen in allen abfragen mit anzugeben, das dbms nimmt sowieso nur die spaltenbezeichner aus der ersten abfrage.
Stilfragen. Wir haben Stil.
e) habe ich dich bereits darauf hingewiesen, dass der union überflüssig ist und man hier besser einen union all einsetzt. ein union versucht immer doppelte werte der unionmenge zu filtern. das ist hier gar nicht gewollt und kostest somit unnütze performance und birgt die potentiale gefahr, dass gewünschte ergebnisse nicht in der ergebnismenge auftauchen.
Du meinst in solchen und ähnlichen Abfragen immer UNION ALL nutzen? Gut, ist eine Stilfrage, uns ging es darum zu zeigen, dass es nicht erforderlich ist, Dubletten auszuschliessen, denn es gibt im Beispiel keine.
f) ich starke zweifel daran habe, das meine abfrage mit den unterabfragen nicht performant sein soll, im gegenteil würde es mich wundern, wäre sie nicht die schnellste.
Deine Polemik und Deine mangelhafte Empathie kann natürlich unter Umständen Gegen-Polemik erzeugen. ;)
g) wenn du schon syntaktische fehler findest, sie dann auch beim namen nennst und nicht irgendwelche behauptungen in dem raum stellst.
Gut, die Aliasnamen sind unzureichend spezifiziert. Die Schreibweisen sehr unschön, gar laienhaft. ;)
yo,
Keine Ahnung, wars wirklich angefordert?
hast du den beitrag von hauke eigentlich gelesen, worum es geht ? dort steht es schwarz auf weiß geschrieben, also was soll das ?
Du wiederholst Dich, wir lieferten ahlt die "Komplettlösung".
selbst wenn du die abfrage auf einen betreiber einschränkt, bekommst du immer noch vier ergebnisdatensätze. wenn du ihren beitrag mal lesen würdest (bekomme immer mehr den anschein, dass du das nicht getan hast), dort steht ein ergebnisdatensatz, den sie bekommen möchte explizit drinne. du lieferst also keine komplettlösung, sondern eine falsche.
uns ging es darum zu zeigen, dass es nicht erforderlich ist, Dubletten auszuschliessen, denn es gibt im Beispiel keine.
denn unsinn deiner aussage kannst du aber selber nicht verstehen oder ? wenn es gar keine dubletten geben kann, wie du selber sagst, warum zum teufel willst du dann mit union auf doubletten prüfen ? ich meine , das ist doch recht einfach zu verstehen, dass ein union dort überflüssig ist und unnötige operationen dem dbms abzwingt. es gibt keine doubletten, aber du prüfst auf doubletten. sag mir doch mal einen grund, worin darin der sinn besteht ?
Deine Polemik und Deine mangelhafte Empathie kann natürlich unter Umständen Gegen-Polemik erzeugen. ;)
die polemik lässt sich ja schnell mit fakten belegen. wie auch bei der diskussion mit dem like kannst du ja beide abfragen gerne auf performance prüfen, die Tabellen hast du ja bereits erstellt. bei geringen datenmengen wird es wohl bei beiden recht performant zugehen. wenn sich aber die tabellen füllen, trennt sich die streu vom weizen. wenn du mir also nicht glauben willst, probiere es einfach aus, dann haben wir gewissheit.
Gut, die Aliasnamen sind unzureichend spezifiziert. Die Schreibweisen sehr unschön, gar laienhaft. ;)
kannst du mir bitte einen syntaktischen fehler in meiner abfrage nennen, welche nach deinen behauptungen vorhanden sein sollen ?
Ilja
Ja, was haben wir denn da.
Keine Ahnung, wars wirklich angefordert?
hast du den beitrag von hauke eigentlich gelesen, worum es geht ? dort steht es schwarz auf weiß geschrieben, also was soll das ?
"Hauke" stört sich am Mehrfach-JOIN, Dein Beitrag intonierte die "n:m". Hast Du da was nicht verstanden? Sollen wirs erklären? Gerne!
Du wiederholst Dich, wir lieferten ahlt die "Komplettlösung".
selbst wenn du die abfrage auf einen betreiber einschränkt, bekommst du immer noch vier ergebnisdatensätze. wenn du ihren beitrag mal lesen würdest (bekomme immer mehr den anschein, dass du das nicht getan hast), dort steht ein ergebnisdatensatz, den sie bekommen möchte explizit drinne. du lieferst also keine komplettlösung, sondern eine falsche.
Häh?
uns ging es darum zu zeigen, dass es nicht erforderlich ist, Dubletten auszuschliessen, denn es gibt im Beispiel keine.
denn unsinn deiner aussage kannst du aber selber nicht verstehen oder ? wenn es gar keine dubletten geben kann, wie du selber sagst, warum zum teufel willst du dann mit union auf doubletten prüfen ? ich meine , das ist doch recht einfach zu verstehen, dass ein union dort überflüssig ist und unnötige operationen dem dbms abzwingt. es gibt keine doubletten, aber du prüfst auf doubletten. sag mir doch mal einen grund, worin darin der sinn besteht ?
Häh? - Bitte ggf. Fragen stellen.
[Gesülze]... probiere es einfach aus, dann haben wir gewissheit.
;)
Gut, die Aliasnamen sind unzureichend spezifiziert. Die Schreibweisen sehr unschön, gar laienhaft. ;)
kannst du mir bitte einen syntaktischen fehler in meiner abfrage nennen, welche nach deinen behauptungen vorhanden sein sollen ?
Schau Dir doch mal die Alias-Tabellennamen an in Deinem Beispiel:
Was ist "u"?
In letzter Zeit kommst Du mir auf die ganz Doofe. Aber no prob, wir helfen gerne. :)
Also, noch einmal ganz klar fürs Archiv und so:
yo Ludger,
deine masche wird langsam alt. du stellst immer wieder wüste behauptungen in den raum und wenn man dem mal nachgeht, dann kommen ausweichende antworten wie ungenügende spezifikationen, komplettlösungen die an der problematik vorbei sind, sinnlose "häh" aussagen oder du versteckst dich hinter deinen king schnully quatsch.
du willst dich hier als profi darstellen und machst einen auf dicke hose, beweist aber tag täglich das gegenteil und bist auf der andere seite nicht manns genug, dir an die eigenen eier zu fassen, für den mist den du verzapfst.
da wir beide ganz offensichtlich nicht miteinander können und ich keine lust mehr auf deinen persönlichen rachefeldzug aus gekränkter eitelkeit habe, ist wohl das beste, du suchst dir jemanden anderen zum spielen und wir schreiben uns einfach nicht mehr gegenseitig auf unsere beiträge.
Ilja
Also, wie gesagt, für Fragen stehen wir weiterhin gerne z.V., ansonsten erzähle Deine kleinen Sorgen und Nöte doch bitte dem Friseur.
Deine Äusserungen sind doch fachlich ganz OK, nur Deine mangelnde Empathie und Dein stures Beharren eine Fragestellung besser verstanden zu haben als alle anderen ist unproblematisch.
Es geht doch oft gar nicht darum die Original-Fragestellungen punktgenau zu beantworten und wenn wir hier eine gute und brauchbare Lösung mit nur einem JOIN vorgestellt haben, die die Datensatzmenge - wie Du bemängelst - vertikal erweitert, so haben wir das doch nur getan um nachzuweisen, dass ein JOIN und eine Unterabfrage und ein UNION statt einem UNION ALL ausreichen um die gewünschten Daten abzufragen.
Und warum haben wir das getan? Richtig, wegen Deiner Fragen und Behauptungen, die ein Zurückweisen benötigten, bspw.
"wenn dann UNION ALL und nicht UNION und zum anderen sollte es in der summe auch wieder vier joins sein."
https://forum.selfhtml.org/?t=147605&m=957451
"[Stuss]"
https://forum.selfhtml.org/?t=147605&m=957544
"["Mängelliste"]" (besonders lustig!)
https://forum.selfhtml.org/?t=147605&m=958000
Also, wir habens nur für Dich getan und nun beschwerst Du Dich, dass Du ein wenig durch den Kakao gezogen wirst.
Na gut, folgende lösung würden wir auch als "profikorrekt" durchgehen lassen:
SELECT
b.Kennzahl,
(
SELECT
u.name
FROM
unternehmen u
WHERE
(u.ident = b.Netz)
) AS Netz_Name,
b.Netz AS Netz_ID,
(
SELECT
u.name
FROM
unternehmen u
WHERE
(u.ident = b.KA)
) AS KA_Name,
b.KA AS KA_ID,
(
SELECT
u.name
FROM
unternehmen u
WHERE
(u.ident = b.Strom)
) AS Strom_Name,
b.Strom AS Strom_ID,
(
SELECT
u.name
FROM
unternehmen u
WHERE
(u.ident = b.Wasser)
) AS Wasser_Name,
b.Wasser AS Wasser_ID,
FROM
betreiber b
WHERE
(b.kennzahl = 100100) -- wenns denn schon sein muss ;)
Wichtig hier, dass die IDs des abgefragten und verzeigerten Objekts ebenfalls abgefragt wird, damit keine Inkonsistenz ensteht. (Bspw. könnten Unternehmen gleiche Namen haben, zumindest reicht das Attribut Name nicht als Eindeutigkeit, vgl. auch die Abfrage "SELECT Name FROM Unternehmen" wenn die Tabelle Unternehmen nur ein Datenfeld Name besässe. - BTW, müsste es nicht "Namen" heissen? ;)
Hallo,
ich danke euch allen schonmal für die schnelle Hilfe.
Bin dabei das alles auszuprobieren :-)
Mfg,
Hauke
yo,
deinen tabellen-struktur hat auf jeden fall klärungsbedarf, wenn nicht sogar änderungsbedarf. bedinkt durch die verteilung der fremdschlüssel auf vier einzelnen spalten(Netz, KA, Strom, Wasser), bekommst du genau die probleme, die du gerade hast. man kann das so machen, allerdings würde ich dir davon abraten.
falls du dennoch dabei bleiben willst, gibt es eine möglichkeit mit unterabfragen. allerdings würde ich dir zu oben genannten daten-design-änderungen raten. ausserdem muss dein dbms unterabfragen unterstützen und die unterabfragen dürfen nur einen wert zurück liefern.
SELECT b.Kennzahl,
(SELECT u.name FROM unternehmen WHERE u.ident = b.Netz) AS Netz,
(SELECT u.name FROM unternehmen WHERE u.ident = b.KA) AS KA,
(SELECT u.name FROM unternehmen WHERE u.ident = b.Strom) AS Strom,
(SELECT u.name FROM unternehmen WHERE u.ident = b.Wasser) AS Wasser
FROM betreiber b
WHERE b.kennzahl = 100100
Ilja
Hallo,
ausserdem muss dein dbms unterabfragen unterstützen und die unterabfragen dürfen nur einen wert zurück liefern.
Muss es nicht, da es mit Joins ein durchaus brauchbares Werkzeug für die Aufgabenstellung gibt.
Grüße
Klaus
yo,
Muss es nicht, da es mit Joins ein durchaus brauchbares Werkzeug für die Aufgabenstellung gibt.
wenn ich mir den posting anschaue, besonders die ergebnismenge von einem datensatz, dann geht das mit joins nur mit zusätzlichem aufwand. insofern würde ich die eine lösung mit den unterabfragen vorziehen.
und die aussage bezog sich nicht darauf, dass es die einzige lösung ist, sondern dass man für diese lösung das dbms unterabfragen unterstützen muss.
Ilja
deinen tabellen-struktur hat auf jeden fall klärungsbedarf, wenn nicht sogar änderungsbedarf. bedinkt durch die verteilung der fremdschlüssel auf vier einzelnen spalten(Netz, KA, Strom, Wasser), bekommst du genau die probleme, die du gerade hast. man kann das so machen, allerdings würde ich dir davon abraten.
Wenn die vier Verzeigerungen nicht nullable sind und zudem keine weiteren Verzeigerungen eingeplant sind, ist das eine sinnvolle Implementation. Die Dir vermutlich vorschwebende "n:m" wäre hier ganz klar zweite Wahl.
Zudem dürften sich die vier Sub-SELECTs als relativ unperformant herausstellen, also auch die Abfrage zweite Wahl. (Syntaktische Fehler und unschöne Schreibweisen lassen wir mal unkommentiert.)