Guten Tag,
es geht um Herrn Zwirbel. Herrn Zwirbel gehört Zwirbels Zwergenzimborium. Herr Zwirbel verkauft Zwerge, Gartenzwerge und andere Zwerge, mit und ohne Zipfel, Zwinge oder Zwickel.
Herr Zwirbel möchte seine Zwergenprodukte in einer Datenbank erfassen. Und jetzt hat er ein Entscheidungsproblem:
Herrn Zwirbels Zwerge bestehen immer aus einer Grundform, die in verschiedenen Ausschmückungen verkauft werden; den Lachzwerg gibt es mit roter oder grüner Zipfelmütze, den Bierzwerg mit großem und kleinem Krug. Ähnliches bei den 789 anderen Zwergenvarianten.
Herr Zwirbel ist nicht aus reinem Glück Multimillionär geworden, nein, sondern weil er in seinen 1580 Ladengeschäften stets die Preise in Schwung hält. Morgens kostet der Zwerg zum Beispiel 12 €, mittags 12,50 € und abends 11 €. Auf so eine gewiefte Preisgestaltung, für dasselbe Produkt zehnmal am Tag den Preis zu ändern, kommt sonst kein Mensch!
Um ganz nah am Kunden zu sein, werden die Geschäfte zudem nur mit den Grundformen beliefert. Das Bemalen der Zwerge oder ihnen einen Krug auf die Umme setzen müssen die Verkäufer selbst, ganz nach regionaler Kundenvorliebe. Herr Zwirbel macht da auch keine Vorgaben, da kann auch mal ein einzelner Wippzwerg mit karierter Hose verkauft werden.
Herr Zwirbel hat nun zwei Tabellen in seiner Datenbank:
Tabelle Zwerge enthält den Produktnamen, Tabelle Preise die einzelnen Preise und dazugehörigen Geschäfte. Wohin nun klugerweise mit der Produktvariante?
Auf den ersten Blick sicher in die Tabelle Zwerge:
Nummer: 1 2 3
Name: Bierzwerg
Variante: 1 Liter 2 Liter
Grundform: 1 1
Grundform zeigt auf die Nummer des "Basiszwerges", das Feld Name bleibt bei den abgeleiteten Zwergen leer und wird aus der Grundform aufgefüllt.
Per select left join mit sich selbst (also der Tabelle, nicht mit Herrn Zwirbel) bekommt Herr Zwirbel sämtliche Zwerge:
select
ifnull(a.name, b.name) as name,
ifnull(a.variante, b.variante) as variante
from zwerge as a
left join zwerge as b on a.nummer = b.grundform
Sollen alle Angebote einer Filiale angezeigt werden, wird's allerdings aufwändig:
select
preise.preis,
zwerge.name,
zwerge.variante
from preise
left join (select
ifnull(a.name, b.name) as name,
ifnull(a.variante, b.variante) as variante
from zwerge as a
left join zwerge as b on a.nummer = b.grundform
) as zwerge
where filiale = "abc"
Die Bauchschmerzen fangen schon damit an, dass sqlite3 und MariaDB bei dieser Abfrage erstmal die komplette Zwergentabelle mit ihren 789 Varianten durcharbeiten. Um die Verarbeitung auf die tatsächlich in einer Filiale angebotenen zehn Varianten zu beschränken, muss der innere select-Teil mit dem where des äußeren bestückt werden.
Deutlich einfacher wäre die Abfrage, wären die Varianten in der Preistabelle untergebracht:
select
zwerge.name,
preise.preis,
preise.variante
from preise
left join zwerge on preis.zwerg = zwerg.nummer
where filiale = "abc";
Die Produktvariante beim Preis unterzubringen statt beim Produkt bereitet Herrn Zwirbel aber Bauchschmerzen, schlimme Bauchschmerzen. Das findet er nicht schön und er grämt sich.
Würde es zeitlich einen nennenswerten Unterschied machen, wäre die Entscheidung klar. Macht es aber nicht, die Abfragen laufen ungefähr gleich schnell ab. Es läuft auf eine ästhetische Entscheidung hinaus, ja, vielleicht sogar eine moralische. Schöne Konstruktionen sind nicht immer einfache Konstruktionen. Auch eine Sanduhr erfüllt ihren Zweck, aber ist das komplexe Uhrwerk einer Taschenuhr nicht um ein Vielfaches erfüllender, nämlich die Seele des technikgeilen Betrachters?
Wer kann Herrn Zwirbel aus seinem Dilemma helfen?
Er hat schon drei Kilo abgenommen.
Wir machen uns Sorgen.
Vielen Dank,
Ziglinde Zwurbel
Zekretariat