AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

SQL Vereinfachen

Ein Thema von Medium · begonnen am 16. Feb 2012 · letzter Beitrag vom 17. Feb 2012
Antwort Antwort
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#1

AW: SQL Vereinfachen

  Alt 17. Feb 2012, 09:36
Danke für die rege Beteiligung!

Das Problem scheint wohl doch komplexer zu sein als ich gestern noch im guten Glauben annahm. Fast alle Lösungen leiden unter dem selben Problem: Ich erhalte eine Liste aller Zielbehälter, die von jedem Rohstoff einzeln erreicht werden können, wobei ich gerne wüsste welche Ziele von allen Rohstoffen gleichsam erreicht werden können. Was ich leicht bekomme ist also:
Code:
rohstoff  zielbehälter
------------------------
   1           101
   1           130
   1           140
   2            50
   2           130
   3            50
   3           101
   3           130
   3           140
Das sind schon nur die Rohstoffe aus einem konkreten Rezept, so dass das schon recht nah an der Lösung ist, wobei ich dies letztlich im Grunde mit einer Mischung eurer Vorschläge erreicht habe:
SQL-Code:
SELECT a.rohstoff, a.behnr FROM
  (SELECT b1.rohstoff, b2.behnr FROM qundz qz
   JOIN beh b1 ON b1.behnr=qz.quelle
   JOIN rohstoffe rs ON b1.rohstoff=rs.rnummer
   JOIN beh b2 ON b2.behnr=qz.ziel) a
INNER JOIN
  (SELECT rohstoff FROM rezpos
   WHERE reznr=:rn AND typ=1) b
USING (rohstoff)
Im Ergebnis sieht man, dass Behälter 130 als einziger von allen Rohstoffen erreicht werden kann, und genau diesen suche ich! (Es kann generell durchaus mehrere Ziele geben bei manchen Rezepturen.)
Im Grunde lande ich, der noch keinen Kaffee hatte, wieder bei etwas ähnlichem von gestern: Rohstoffe pro Ziel zählen, und mit der Anzahl Rohstoffe im Rezept vergleichen. Das geht doch sicherlich hübscher

@shima: Ich habe den Primärindex nur auf der (an sich hier eher unbeteiligten) Spalte "id" liegen, aber einen UNIQUE-Index auf (quelle, ziel). Beraube ich mich da ggf. Vorteile, die ich im Primärindex hätte wie du ihn vorschlägst?

Danke euch schon mal!
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.656 Beiträge
 
Delphi 12 Athens
 
#2

AW: SQL Vereinfachen

  Alt 17. Feb 2012, 09:47
Die Lösung von omata bringt auch nicht das gewünschte Ergebnis? Etwas Ähnliches hatte ich nämlich auch im Sinn: zuerst alle passenden per INNER JOIN ermitteln und dann die Anzahl mit der der Rezeptpositionen vergleichen.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#3

AW: SQL Vereinfachen

  Alt 17. Feb 2012, 10:10
@DeddyH: Da habe ich ein recht ähnliches Problem: Ich bekomme ohne das HAVING dort alle Ziele, die ebenfalls einzeln pro Rohstoff erreicht werden (allerdings ohne Dopplungen). Obiges Beispiel sähe hier also so aus:
Code:
zielbehälter
--------------
     50
    101
    130
    140
Mit der HAVING Klausel ist das Ergebnis leer, auch wenn es mindestens ein mögliches Ziel sicher gibt (so konstruiert).

@jobo: Sorry, ja es soll eine Liste werden, die alle Zielbehälter führt, in denen ein gewähltes Rezept angefertigt werden kann. Am Ende geht es darum, dem Anlagenfahrer eine Combobox mit diesen anzuzeigen, wenn er ein Rezept zur Produktion vorgeben möchte. Dies können 0-N Ergebnisse sein, wobei Rezepte mit 0 Zielen wohl als ungültig interpretiert werden müssen
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.739 Beiträge
 
Delphi 6 Enterprise
 
#4

AW: SQL Vereinfachen

  Alt 17. Feb 2012, 10:34
Ausgehend von deiner Ergebnismenge in #8:


Select zielbehaelter, count(zielbehaelter)
From (DerSelectDerDeineErgebnismengeLiefert)
Group By zielbehaelter
Having count(zielbehaelter) = (SelectDerDieAnzahlAnZutatenLiefert)

Ist arg konstruiert und wenig elegant, aber sollte die Ergebnisliste liefern.
Ralph
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#5

AW: SQL Vereinfachen

  Alt 17. Feb 2012, 11:45
Das war auch mein Gedanke. Letztlich von meiner ersten Lösung gestern nicht allzuweit entfernt, jedoch sind die Sub-Selects in dieser Variante nun erheblich leichter nachvollziehbar, so dass man da ggf. auch nach ein paar Monaten noch heruasfinden kann, was da überbaupt gemacht wird. Das war letzlich auch das Ziel meiner Frage: Funktionierende Lösung, die etwas weniger verworren ist, als das was ich da produziert hab

Stand:
SQL-Code:
SELECT x.behnr, x.name FROM
  (SELECT a.rohstoff, a.behnr, a.name FROM
    (SELECT b1.rohstoff, b2.behnr, b2.name FROM qundz qz
    JOIN beh b1 ON b1.behnr=qz.quelle
    JOIN beh b2 ON b2.behnr=qz.ziel
    JOIN rohstoffe rs ON b1.rohstoff=rs.rnummer) a
  INNER JOIN
    (SELECT rohstoff FROM rezpos WHERE reznr=:rn AND typ=1) b
  USING (rohstoff)) x
GROUP BY
  x.behnr
HAVING
  COUNT(x.behnr) >= (SELECT COUNT(*) FROM rezpos WHERE reznr=:rn AND typ=1)
">=", weil ich noch nicht weiss, ob ggf. später mehrere Quellbehälter auf ein und dem selben Ziel den selben Rohstoff beinhalten können. Es kann also auch mehr Quellen als Rohstoffe im Rezept geben, was denke ich durch das >= (statt =) behandelt sein sollte.

Zu vormals:
SQL-Code:
SELECT k.ziel, e.name FROM
  (SELECT COUNT(*) qcount, z.ziel FROM
    (SELECT p.id, q.ziel FROM beh b
    JOIN (SELECT id, rohstoff FROM rezpos WHERE reznr=:rn AND typ=1) p ON b.rohstoff = p.rohstoff
    JOIN qundz q ON b.behnr = q.quelle) z
    GROUP BY z.ziel) k
  JOIN (SELECT COUNT(id) mcount FROM rezpos WHERE reznr=:rn AND typ=1) m
JOIN beh e ON k.ziel=e.behnr
WHERE mcount<=qcount
Das Ergebnis scheint gleich zu sein, und auch wenn die neue Variante länger ist, finde ich sie doch weit eingängiger. Die Mechanismen dürften bei beidem aber am Ende doch recht ähnlich sein, und wenn auch ihr intuitiv nicht zu einem Einzeiler kommt, bin ich jetzt zumindest davon überzeugt, dass ich das Problem deutlich unterschätzt habe

Besten Dank!
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman
Online

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.429 Beiträge
 
Delphi 12 Athens
 
#6

AW: SQL Vereinfachen

  Alt 17. Feb 2012, 11:51
[OT]
nur so aus Interesse...

Ist die Komplexität der SQL Abfrage vergleichbar mit dem Design der DB ? Sprich je komplexer das SQL um so bescheidener das DB Design... und umgekehrt ?
[/OT]
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#7

AW: SQL Vereinfachen

  Alt 17. Feb 2012, 12:02
@haentschman: Die DB ist nicht perfekt, aber durchaus gut strukturiert. Das ist auch das erste Mal, dass ich in dem Projekt so etwas großes an SQL brauchte. Ehemals wurde diese Funktionalität in einer grausigen Delphi-Routine gemacht, die in 3 Queries zigfach rumgeschleift ist. Das wollte ich eigentlich nur aufhübschen
Das knifflige hier ist wohl vor allem, dass in den Rezepten Rohstoffe stehen, und nicht direkt die Quellbehälter. Die sind zwar meistens 1:1 zugeordnet, aber ich musste Rohstoffe und Behälter jetzt entkoppeln, da jetzt teilweise wechselnde Rohstoffe in den gleichen Quellen gelagert werden.

Die Struktur der Tabellen ist in #1 angedeutet.

@Jumpy: In der Tat! Ui, danke für den Hinweis.
Die unterschiedlichen Kombis sind möglich, jedoch brauche ich diese hier nicht konkret. Ich muss nur wissen "es geht". Ich guck mal, wo das Distinct hin müsste, das sollte aber so gehen. Danke!
\\Edit: Ein DISTINCT im 2. Subselect (SELECT DISTINCT b1.rohstoff, b2.behnr, b2.name FROM qundz qz) tut das richtige. Es ist damit sogar richtig behandelt, wenn ich in einem Rezept mehr als eine Position mit dem selben Rohstoff habe! Ich glaube, das ist schon ganz okay so.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)

Geändert von Medium (17. Feb 2012 um 12:10 Uhr)
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.739 Beiträge
 
Delphi 6 Enterprise
 
#8

AW: SQL Vereinfachen

  Alt 17. Feb 2012, 11:55
">=", weil ich noch nicht weiss, ob ggf. später mehrere Quellbehälter auf ein und dem selben Ziel den selben Rohstoff beinhalten können. Es kann also auch mehr Quellen als Rohstoffe im Rezept geben, was denke ich durch das >= (statt =) behandelt sein sollte.
Da bitte Vorsicht walten lassen! In der zukünftigen Mehrbehältervariante könnten bei z.B. 4 benötigten Rohstoffe jeweils 2 der Rohstoffe aus mehreren Quell-Behältern kommen und im Zielbehäter landen Somit ist der count >= Anz. Rohstoffe, obwohl ggf. noch nichtmal alle Rohstoffe im Behälter landen sondern nur zwei, diese dafür aber mehrmals.

Dies wird verhindert, indem in dem "Zwischenselekt" irgendwie ein Distinct auf die Rohstoff+Ziel gemacht wird, so dass mehrere Quellen eines Rohstoffes die auf das selbe Ziel kommen nicht mehrfach berücksichtigt werden. Dann würde auch das "=" ausreichen.

Je mehr ich aber darüber nachdenke und das hier schreibe, kommen mir aber Zweifel, das die Lösung 100% wasserdicht ist. Es kann ja für einen Zielbehälter mehrere passende Kombis aus Quellbehältern geben, um das Ziel zu erreichen.
Ralph
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#9

AW: SQL Vereinfachen

  Alt 17. Feb 2012, 09:53
Das Problem scheint wohl doch komplexer zu sein als ich gestern noch im guten Glauben annahm. Fast alle Lösungen leiden unter dem selben Problem: Ich erhalte eine Liste aller Zielbehälter, die von jedem Rohstoff einzeln erreicht werden können, wobei ich gerne wüsste welche Ziele von allen Rohstoffen gleichsam erreicht werden können. Was ich leicht bekomme ist also..


Im Ergebnis sieht man, dass Behälter 130 als einziger von allen Rohstoffen erreicht werden kann, und genau diesen suche ich! (Es kann generell durchaus mehrere Ziele geben bei manchen Rezepturen.)
Das Problem ist vielleicht auch, dass Du die Aufgabenstellung nicht präzise formulierst- bis jetzt. Was bedeutet denn "kann auch mehrere"? Kann sein, dass es die gibt, interessiert mich aber nicht?
Ich will jeden einzelnen Zielbehälter, der geht (Sonst wird es ja keine Liste)?
..
Gruß, Jo
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:38 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