Mysql Frage

alles zu mySql/mariadb

Moderator: Moderatoren

Antworten
Benutzeravatar
jackDuijf
Rookie
Rookie
Beiträge: 4
Registriert: Mi, 10. Dez 2014 22:06
Kontaktdaten:

Mysql Frage

Beitrag von jackDuijf »

Hallo,
Dies ist meine erste Frage in dieses Forum. :D
Ich soll Daten aus eine MySQL Datei über ODBC einlesen.
Den richtigen Sql Auftrag krieg Ich nicht zusammen.....

Tabelle "Artikel"
AR_ID
AR_NAME
AR_BARCODE

Tabelle "Prijs"
AP_AR_ID (Ist gleich AR_ID)
AP_DATUM
AP_PRIJS

Von jedes record in "Artikel" gibt es mehere records in "Prijs". Jedes record hat einen einzigartige AP_DATUM
Welcher Sql auftrag gift mir eine recordset mit die folgende daten?

AR_ID
AR_NAME
AR_BARCODE
AP_DATUM (neueste datum)
AP_PRIJS (Preis bei neueste datum)

Von jedes "Artikel" ist nur eine Zeile erwünscht mit den letzt bekanten Prijs und Preisdatum

M.fr.gr,
Jack Duijf
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Mysql Frage

Beitrag von georg »

Guten Morgen, Jack -


fangen wir einfach einmal an:

Code: Alles auswählen

SELECT * FROM artikel LEFT JOIN prijs ON ar_id = ap_ar_id
Dies bringt eine Verbindung aller JOINbaren Sätze.

Für einen kleinen Test:

Code: Alles auswählen

mysql> create table artikel (ar_id int, ar_name char(20), ar_ean int);
Query OK, 0 rows affected (0.16 sec)

mysql> create table prijs (ap_ar_id int, ap_date date, ap_prijs decimal(7,2));
Query OK, 0 rows affected (0.08 sec)

mysql> insert into artikel values(1, 'Petersilie', 12345), (2, 'Graubrot', 56789), (3, 'Schaufel', 90123);
Query OK, 3 rows affected (0.03 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> insert into prijs values(1, '2014-12-01', 1.22), (1, '2014-12-05', 1.25);
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into prijs values(2, '2014-12-08', 2.50), (3, '2014-11-30', 11.11);
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into prijs values(3, '2014-12-07', 11.20), (4, '2013-01-01', 9.99);
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

Code: Alles auswählen

artikel:
1 | Petersilie | 12345
2 | Graubrot   | 56789
3 | Schaufel   | 90123

Code: Alles auswählen

prijs:
1 | 20141201 | 1.22
1 | 20141205 | 1.25
2 | 20141208 | 2.50
3 | 20141130 | 11.11
3 | 20141207 | 11.20
4 | 20130101 | 9.99

Code: Alles auswählen

Ergebnis:
1 | Petersilie | 12345 | 1 | 20141201 | 1.22
1 | Petersilie | 12345 | 1 | 20141205 | 1.25 <=
2 | Graubrot   | 56789 | 2 | 20141208 | 2.50 <=
3 | Schaufel   | 90123 | 3 | 20141130 | 11.11
3 | Schaufel   | 90123 | 3 | 20141207 | 11.20 <=
Da es ein LEFT JOIN ist, enthält das Ergebnis alle Sätze aus der links stehenden Datei (artikel), sowie alle Sätze aus der rechts stehenden Datei (prijs), die über ar_id = ap_ar_id zugeordnet werden können.

Du benötigst aber nur die Sätze, die ich mit '<=' gekennzeichnet habe. Da es in prijs mehrere Sätze geben kann, müssen wir das ganze über GROUP und SORT einschränken. Unternehmen wir den ersten Versuch:

Code: Alles auswählen

mysql> select ar_id, ar_name, ar_ean, ap_ar_id, max(ap_date), ap_prijs from artikel left join prijs on ar_id = ap_ar_id
group by ar_id order by ar_id, ap_date;
+-------+------------+--------+----------+--------------+----------+
| ar_id | ar_name    | ar_ean | ap_ar_id | max(ap_date) | ap_prijs |
+-------+------------+--------+----------+--------------+----------+
|     1 | Petersilie |  12345 |        1 | 2014-12-05   |     1.22 |
|     2 | Graubrot   |  56789 |        2 | 2014-12-08   |     2.50 |
|     3 | Schaufel   |  90123 |        3 | 2014-12-07   |    11.11 |
+-------+------------+--------+----------+--------------+----------+
3 rows in set (0.00 sec)
Das sieht zwar schon gut aus, aber es wird immer der erste Preis für einen Artikel aus prijs genommen. Das liegt daran, dass man darauf (leider) keinen Einfluss hat.

Aber wir haben jetzt ein Result Set, das alle Informationen enthält, die wir brauchen, um an das gewünschte Ergebnis zu kommen: wir kennen sowohl ar_id als auch das neueste ap_date.

Ein Result Set kann auch erzeugt werden, wenn ich in einem anderen Result Set nachschaue, welche Sätze in haben will. Die vorhergehende SELECT-Anweisung erzeugt mir dieses Result Set. Ich reduziere die Anweisung auf die beiden Felder ar_id und ap_date und greife auf mein erstes SELECT zurück, filtere aber auf die Sätze, die sich in dem Result Set mit GROUP und SORT finden:

Code: Alles auswählen

mysql> select * from artikel left join prijs on ar_id = ap_ar_id where (ar_id, ap_date) in (select ar_id, max(ap_date) from artikel left join prijs on ar_id = ap_ar_id group by ar_id order by ar_id, ap_date);
+-------+------------+--------+----------+------------+----------+
| ar_id | ar_name    | ar_ean | ap_ar_id | ap_date    | ap_prijs |
+-------+------------+--------+----------+------------+----------+
|     1 | Petersilie |  12345 |        1 | 2014-12-05 |     1.25 |
|     2 | Graubrot   |  56789 |        2 | 2014-12-08 |     2.50 |
|     3 | Schaufel   |  90123 |        3 | 2014-12-07 |    11.20 |
+-------+------------+--------+----------+------------+----------+
3 rows in set (0.00 sec)
Beginnen wir mit

Code: Alles auswählen

(select ar_id, max(ap_date) from artikel left join prijs on ar_id = ap_ar_id group by ar_id order by ar_id, ap_date)
Mit diesem SELECT isoliere ich Artikel und Datum.

Und dann fordere ich alle Felder an aus dem LEFT JOIN, wobei ich als Bedingung setze, dass die Sätze (was ar_id und ap_date angeht) durch das in Klammern stehende SELECT ausgewählt wurden.

Code: Alles auswählen

where (ar_id, ap_date) in
Dies weist den Server an, für jede Zeile im Result Set zu prüfen, ob die Kombination ar_id und ap_date in dem Result Set steht, das in Klammern steht. Ist das der Fall, wird die Zeile verwendet, gibt es keine Übereinstimmung, wird die Zeile nicht verwendet.

Ich hoffe, ich konnte das einigermassen deutlich erklären.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Mysql Frage

Beitrag von brandelh »

zumindest ICH fand es sehr interessant und so wild ist das "normale" SQL ja auch nicht, ich müsste nur damit anfangen ... :roll:

Dass bei der Abfrage mit dem MAX() aber von der zweiten Datei Daten aus verschiedenen Sätzen angezeigt werden, damit hätte ich nicht gerechnet:

Code: Alles auswählen

gesucht:
|1 | Petersilie | 12345 | 1 | 20141205 | 1.25
geliefert:
|1 | Petersilie | 12345 | 1 | 2014-12-05 | 1.22 |
so komplexe SQL Suchen habe ich bisher - auch um sie selbst noch verstehen zu können - aufgeteilt und lieber per Programm gemischt.
Gruß
Hubert
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Mysql Frage

Beitrag von georg »

Hallo, Hubert -


das ist ja der Vorteil von solchen SQL-Konstrukten, dass man damit Programm-Code auf den SQL-Server verlagern kann.

Man darf an der Stelle auch nicht aus den Augen verlieren, dass es sich bei GROUP BY um eine Aggregierungsfunktion handelt. Die Aggregat-Ebenen sind:

ar_id
ap_date

Werte, die unterhalb dieser Ebene liegen, sind von ihrer Herkunft unbestimmt, wenn mehrere Zeilen zur Verfügung stehen. Das ist auch gut so und sollte uns als Programmierer dazu bringen, solche Aggregat-Funktionen eben auch nur dafür zu verwenden. Denn sonst verhält sich unser Programm auf einmal anders, wenn der Server aktualisiert wird und eine andere Verhaltensweise an den Tag legt.

Zum einen musste ich die Lösung erst einmal selbst ableiten, zum anderen war es ein guter Zwischenschritt auf dem Weg, die richtige Anweisung abzuleiten.

Insgesamt sind solche Konstrukte aber genau das, was man braucht, wenn man die SET RELATION aus Xbase++ in SQL abbilden will: das passiert das gleiche: aus der rechts stehenden Datei wird nur ein Satz ausgewählt (normalerweise der Satz, der im Index "vorne" steht).
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Mysql Frage

Beitrag von brandelh »

georg hat geschrieben:Insgesamt sind solche Konstrukte aber genau das, was man braucht, wenn man die SET RELATION aus Xbase++ in SQL abbilden will
set relation konnte ich noch nie leiden, ich habe normalerweise ein dbseek() je DBF Datei gemacht :-)
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Mysql Frage

Beitrag von Jan »

Hubert,

da stimme ich Dir zu. Das kostet zwar ein paar Zeile Code mehr, aber läuft garantiert so wie ich das will. Selbst wenn der alte Bug in den Relations anscheinend inzwischen behoben zu sien scheint.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Mysql Frage

Beitrag von georg »

Hallo,


ich teile Eure Auffassung in Bezug zu SET RELATION. Aber viele von uns haben mit altem Code zu tun, der eben auch solche Konstrukte verwendet, und dann ist die Frage "Kann ich das in SQL abbilden?"
oft sehr wichtig für die Entscheidung, SQL für die Datenhaltung zu verwenden. Daher mein Hinweis.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Mysql Frage

Beitrag von brandelh »

und wir verschlingen deine SQL Ausführungen =D> :D
Gruß
Hubert
Benutzeravatar
jackDuijf
Rookie
Rookie
Beiträge: 4
Registriert: Mi, 10. Dez 2014 22:06
Kontaktdaten:

Re: Mysql Frage

Beitrag von jackDuijf »

Hallo,

Vielen Dank für die sehr Lehrsame Antwort. =D>
Hier mit kann Ich mein Problem lösen.

M.fr.gr,
Jack Duijf
Antworten