SQL Query Frage

Krischu

Benutzer
Beiträge
7
Schönes Wochenende und Gruß allerseits.
Bin neu hier im Forum und hoffe darauf, hier auf SQL-Experten zu treffen, die mir beim Lösen eine DB-Abfrage helfen.
Ich bin kein versierter SQL Programmierer und kenne nur die Grundlagen und habe eine ungefähre Ahnung, wie ich folgendes Problem, was sicher eine typische Anwendung darstellt, angehen müßte.

Ich habe mySql gewählt, weil ich es auf vielen System zur Verfügung habe.
Problemstellung:


Ich habe eine CSV Datei (als export einer "Numbers-Datei - macOS"), die Produkte enthält. Die Tabelle Produkte
enthalte mal: (Tabelle1.csv)

ArtikelNr Name Preis weitereInfo


Dann habe ich eine weitere CSV Datei eines weiteren Numbers-Dokuments: (Tabelle2.csv)

Name Suk

(Suk entspricht der ArtikelNr der ersten Tabelle)

Die Anfrage soll alle Zeilen aus Tabelle 1 enthalten, deren ArtikelNr in Spalte Suk der Tabelle 2 vorkommt.


Ausgehend von einer leeren Datenbank würde ich dann wie vorgehen?

create database alles

import Tabelle1.csv
import Tabelle2.csv

(die csv-Dateien haben die Spaltennamen in jeweils der ersten Zeile, wie das so üblich ist).

Wie sieht jetzt das SQL statement aus?

Ich formuliere es mal naiv:

SELECT * from Tabelle1 where (SELECT Suk from Tabelle2) IN ArtikelNr ;
 
Werbung:
Select * from Tabelle1 ist ok. Optimal ist explizit die Spalten hinzuschreiben, die man ausgeben will, auch wenn es alle sind. Das ist eine gute Angewohnheit, besser als * zu nutzen.

Das
..where.. kann man machen, ist aber für die Verknüpfung 2er Tabellen out.
besser:
join

Also zusammen:
Select * from
Tabelle1 t1 join Tabelle2 t2
on t1.ArtikelNr = t2.suc

(fertig)

mit join..on definierst Du die zu verknüpfenden Felder.
t1, t2 sind dabei Aliase (Kurzform des Tabellennamens, beliebig wählbar), die es übersichtlicher macht und mehr Funktionalität bietet. Immer nutzen, auch bei nur einer Tabelle im Statement. Ebenfalls eine gute Angewohnheit.
Der "pure" join Befehl führt zu der von Dir gewünschten Mengenbeschränkung, es gibt Varianten davon, die nicht zu einer Mengenbeschränkung führen! Stichwort ist "Outer Join", am besten mal nachschlagen und verstehen. Kannst Du mit Deinen Daten auch gleich ausprobieren, versteht sich dann gleich viel besser.

Ein ..where.. würde man am Ende nutzen, wenn man die Menge der ausgegebenen Daten filtern will. Achtung dabei, jenachdem auf welcher Tabelle der Filter liegt, kann das ungeahnte Effekte bei Outer Joins haben! Bei Bedarf nachlesen oder fragen..

Und noch dazu
(SELECT Suk from Tabelle2) IN ArtikelNr würde man idR andersrum schreiben:
ArtikelNr in (SELECT Suk from Tabelle2)

Eine solche Notation nutzt man eher, wenn das Select in Klammern eine kleine, relativ statische Menge ergibt. Moderne SQL Engines / Optimizer können damit allerdings heute ganz gut umgehen und es je nach Einsatz "optimal" in einen guten Ausführungsplan verwandeln.
Problem ist eher das "Leseverständnis", wenn man einen Join möchte, sollte man auch Join schreiben (und kann dann ggF. sehr leicht auch die Outervarianten nutzen, falls benötigt)
 
Danke. Das liest sich schon mal gut. Wenn ich da angekommen bin, werde ich es ausprobieren. Der Weg dahin ist noch steinig:
Meine CSV-Dateien enthalten Texte in den Columns, die über mehrere Zeilen gehen. Etwa so:


Code:
AB-214 ; "Monsieur XY ^M
ist von Beruf ^M
Kommissar"
DE-332 ; "Monsignore Peppone ^M
ist ^M
blah blah"
NO-333;"weiterer ^M
über ^M
mehrere ^M
Zeilen"

usw.
create table alles ( artnr varchar(32) , beschreibung varchar(1024) ) ;
load data local infile "alles.csv" INTO TABLE alles COLUMNS TERMINATED BY ';' ;

Momentan wird in der Tabelle "alles" für jede Zeile im Feld B"Beschreibung" eine neue ROW aufgemacht, mit leerem Eintrag für artnr.

Ich muß dem Import irgendwie beibringen, daß er die mehrzeilige Beschreibung als eine Einheit betrachtet.
Ah ja, mit ENCLOSED BY '"' bringt schon mehr.
 
Zuletzt bearbeitet:
Die meisten DB erlauben es String Delimiter zu definieren, bei Dir offenbar "
Das kann schon helfen.
Ich arbeite nicht mit mySQL, deswegen kann ich da aus dem Stand nichts weiter zu sagen.
Doku von load:
[{FIELDS | COLUMNS}
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
 
Gerade ist es mir gelungen, mittels dieses LOAD, die Daten einzulesen:

Code:
load data local infile "alles.csv" INTO TABLE alles COLUMNS TERMINATED BY ';' optionally enclosed by '"' escaped by '"' lines terminated by '\r'

Jetzt wollte ich mal kontrollieren und gab

SELECT ARTNR FROM alles WHERE artnr LIKE 'BUG123';

Gibt Empty Set (0) zurück. ArtNr BUG123 ist aber definitiv im Datenfeld ArtNr vorhanden.

LIKE '%BUG123' bringt Treffer. Muß wohl doch die Doku von WHERE mit LIKE noch mal lesen.
 
Zuletzt bearbeitet:
Bei mir kamen schon Selbstzweifel auf. Hatte WHERE entry='XYZ'; doch immer funktioniert. Warum jetzt auf einmal nicht? Und LIKE funktioniert auf einmal nicht, wie ich es gewohnt war. Folgendes:

Code:
mysql> select artnr from alles where artnr='BUG13';
Empty set (0.00 sec)

mysql> select artnr from alles where artnr like '%BUG13';
+--------+
| artnr  |
+--------+
|
BUG13 |
+--------+
1 row in set (0.00 sec)

mysql> select artnr from alles where artnr='\rBUG13';
Empty set (0.01 sec)

mysql> select artnr from alles where artnr='\nBUG13';
+--------+
| artnr  |
+--------+
|
BUG13 |
+--------+
1 row in set (0.01 sec)

mysql>

In der CSV-Datei ended die 2. Spalte (mehrzeiliger Text) auf:


Code:
^M
Ende Spalte 2 der n-1 Zeile."^M
BUG13;"2. Spalte der n-ten Zeile

Das ^M ist also noch Bestandteil des Strings von "artnr". (Sieht man auch in der tabellarischen Ausgabe - Umbruch nach dem | ). Suche da noch nach einer Lösung. Hat zwar nicht direkt etwas mit der Frage zu tun, ist aber momentan ein Spielverderber.
 
Select * from Tabelle1 ist ok. Optimal ist explizit die Spalten hinzuschreiben, die man ausgeben will, auch wenn es alle sind. Das ist eine gute Angewohnheit, besser als * zu nutzen.

Das
..where.. kann man machen, ist aber für die Verknüpfung 2er Tabellen out.
besser:
join

Also zusammen:
Select * from
Tabelle1 t1 join Tabelle2 t2
on t1.ArtikelNr = t2.suc

(fertig)
Wenn ich das Ergebnis gleich in eine Tabelle schreiben will, wie ginge das dann?
 
Werbung:
Zurück
Oben