![]() |
AW: Abfrage: Kund hat Artikel X aber nicht Y gekauft
Da es mir keine Ruhe lässt, eine Lösung ohne Subselect zu finden, hab' ich mal den ChatBot meiner Wahl befragt, diese Lösung wurde extrem schnell geliefert:
Zitat:
Zitat:
SQL-Code:
SELECT k.*
FROM Kunden k WHERE EXISTS ( SELECT 1 FROM Rechnungen r JOIN Positionen p ON r.ReNr = p.ReNr WHERE r.KdNr = k.KdNr AND p.Artikel = 'X' ) AND NOT EXISTS ( SELECT 1 FROM Rechnungen r JOIN Positionen p ON r.ReNr = p.ReNr WHERE r.KdNr = k.KdNr AND p.Artikel = 'Y' ) Zitat:
Zitat:
Zitat:
SQL-Code:
SELECT k.KdNr, k.Name
FROM Kunden k JOIN Rechnungen r ON k.KdNr = r.KdNr JOIN Positionen p ON r.ReNr = p.ReNr GROUP BY k.KdNr, k.Name HAVING SUM(CASE WHEN p.Artikel = 4701 THEN 1 ELSE 0 END) > 0 AND SUM(CASE WHEN p.Artikel = 5702 THEN 1 ELSE 0 END) = 0 Zitat:
|
AW: Abfrage: Kund hat Artikel X aber nicht Y gekauft
sum über case ist aber vermutlich die langsamste Variante, weil dies kaum optimiert werden kann. Meine letzte Variante ist auch kein echtes Subselect, weil die zweite Abfrage mit join kombiniert und nicht in jeder Zeile ausgeführt wird.
Holger hat mit seinem Einwand aber natürlich auch Recht: Zitat:
|
AW: Abfrage: Kund hat Artikel X aber nicht Y gekauft
Zitat:
SQL-Code:
Allerdings lassen die nur rudimentär vorhandenen Testdaten eigentlich keine belastbare Aussage zu.
SELECT K.KdNr, K.Name
FROM Kunden K INNER JOIN Rechnungen R ON K.KdNr = R.KdNr LEFT JOIN Positionen P1 ON R.ReNr = P1.ReNr AND P1.Artikel = 4701 LEFT JOIN Positionen P2 ON R.ReNr = P2.ReNr AND P2.Artikel = 5702 GROUP BY K.KdNr, K.Name HAVING COUNT(P1.ReNr) > 0 and COUNT(P2.ReNr) = 0; Unschön ist halt, dass man die Kunden-Felder zumindest im GROUP BY einzeln aufführen muss (Ich kenne zumindest kein System, das dort ein K.* akzeptiert). Allerdings ist man dann vielleicht eher gewillt, nur die wirklich benötigten Felder anzugeben. Wäre ja denkbar, dass lediglich die KdNr benötigt wird, dann wird es recht simpel. |
AW: Abfrage: Kund hat Artikel X aber nicht Y gekauft
Zitat:
Zitat:
Zitat:
Zitat:
![]() Interessant ist: Wir haben jetzt acht unterschiedliche und funktionierende Lösungen zur Aufgabenstellung. |
AW: Abfrage: Kund hat Artikel X aber nicht Y gekauft
Zitat:
|
AW: Abfrage: Kund hat Artikel X aber nicht Y gekauft
so als technische basisinfo noch:
ein sum befehl wird immer die komplette ergebnismenge abklappern, spricht, wenn du tausend kunden hast die alle je 1000 rechnungen mit dem verkauften produkt hatten, kommt der server nicht drumherum, alle eine Million datensätze zu analysieren, um die komplett unwichtige Information der summe zu ermitteln (war ja im threadtitel irrelevant). Ein exists ist zumindest bei firebird so implementiert, das dieser sobald ein record in der ergebnismenge gefunden wurde (bei der hoffentlich passende indizes nutzbar sind) sofort die weiteren teilergebnisse ignoriert, also in dem o.a. fall mit passenden indizes statt 1000000 operationen das ergebnis mit 1000 operationen ermitteln kann. Bei single user datenbanken wird das kaum keiner merken, wenn aber dutzende oder hunderte user solche abfragen in schlechter version parallel machen und so ermittelte unwichtige count oder sum befehle auf einem Startscreen einer Applikation darstellt, dann wird der server niemals performant sein, weil der immer nur schwachsinn mit mörderaufwand treibt. wenn dann noch dazu kommt, das die 1000000 rechnungen und die 1000 kunden nicht über passende indizes verfügen, reden wir auch intern nicht über 1000000 operationen sondern schnell mal über 1000000000 operationen. firebird liefert sehr gute hilfsmittel um so was für die eigenen SQLs zu erkennen, aber das Design der eigenen SQLs muss der programmierer verantworten. Wenn man eine summe brauchen würde geht es nicht anders, aber aus der summe >= eigentlich nur die existenz auszuwerten ist um es mal freundlich zu sagen unglücklich programmiert. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz