WHERE-Abfrage nach Zahlen (getrennt mit Komma oder Semikolon)
Stoffel
- datenbank
3 Vinzenz Mai1 Felix Riesterer0 suit
Hallo,
was hab ich heute Abend gesucht - darum sei es mir verziehen, wenn ich mal kurz vor für mich LMAA sagen muss.
Also: Ich habe zwei Tabellen in MySQL:
texte
ID | Text | Quelle
------------------
1 | abc | 1
------------------
2 | def | 2
------------------
3 | ghi | 3
------------------
quellen
QID | Quellenname
-----------------
1 | Amazon
-----------------
2 | Ebay
-----------------
3 | Rebuy
-----------------
Wenn ich die jetzt mit meinem laienhaften Wissen verknüpfe, funktioniert das ganz gut.
$sql = "SELECT * FROM texte a, quelle q WHERE a.id = q.qid ORDER BY qid DESC";
Ich hielt es für angebracht, das über zwei Tabellen zu lösen und bin, wie gesagt, noch im "Laien-Modus" :-). Sollte es dafür also eine bessere Lösung geben, bitte ich dies zu entschuldigen. Zurück zum Thema...
Wie muss denn meine Abfrage aussehen, wenn sich meine Quelle auf 1;2 verändert, also mehr als eine Quelle angegeben ist...
texte
ID | Text | Quelle
------------------
1 | abc | 1;2
------------------
2 | def | 1;2;3
------------------
3 | ghi | 1;3
------------------
Das Ziel soll quasi sein, dass zum Text abc zwei Quellen ausgegeben werden (in dem Fall Amazon und Ebay)
Ich habe mich mit LIKE und REGEXP versucht, aber keine ultimative Lösung gefunden. Ich meine: Gibt's eine ultimative Lösung überhaupt für das Problem oder soll ich die Quellen anders anordnen als mit Zahlenwerten?
Vielen vielen Dank!
Hallo,
Also: Ich habe zwei Tabellen in MySQL:
texte
ID | Text | Quelle1 | abc | 1
2 | def | 2
3 | ghi | 3
quellen
QID | Quellenname1 | Amazon
2 | Ebay
3 | Rebuy
Wenn ich die jetzt mit meinem laienhaften Wissen verknüpfe, funktioniert das ganz gut.
$sql = "SELECT * FROM texte a, quelle q WHERE a.id = q.qid ORDER BY qid DESC";
Naja, explizite Joins sind einfach viel schöner und klarer:
~~~sql
SELECT
*
FROM
texte t -- besserer Aliasname als "a"
INNER JOIN
quellen q
ON
a.Quelle = q.QID -- ist vermutlich richtiger als Dein a.id :-)
ORDER BY
qid DESC
Ich hielt es für angebracht, das über zwei Tabellen zu lösen und bin, wie gesagt, noch im "Laien-Modus" :-). Sollte es dafür also eine bessere Lösung geben, bitte ich dies zu entschuldigen. Zurück zum Thema...
zwei Tabellen sind in dem Fall, dass es genau eine Quelle gibt, durchaus richtig.
Wie muss denn meine Abfrage aussehen, wenn sich meine Quelle auf 1;2 verändert, also mehr als eine Quelle angegeben ist...
wenn es zu jedem Text mehr als eine Quelle geben kann und jede Quelle mehr als einem Text zugeordnet werden kann, dann hast Du eine n:m-Beziehung und benötigst in den üblichen DBMS eine Verknüpfungstabelle. Es ist gar keine gute Idee, die Daten *nicht* atomar abzulegen.
texte
ID | Text |1 | abc |
2 | def |
3 | ghi |
text_quellen
id_text | id_quelle
-------------------
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 3
Die Zuordnung von Texten und Quellen erhältst Du nun über zwei Joins:
SELECT
t.id,
t.text,
q.QID,
q.Quellenname
FROM
texte t
INNER JOIN
text_quellen tq
ON
t.id = tq.id_text
INNER JOIN
quellen q
ON
tq.id_quelle = q.QID
Das ist die ultimative Lösung.
Lesetipps:
Einführung in Joins
Fortgeschrittene Jointechniken
Freundliche Grüße
Vinzenz
... zwischen Tür und Angel versteh ich's noch nicht auf den ersten Blick, aber heute Abend habe ich mehr Zeit und werde es mit Hilfe der Links sicherlich hinbekommen.
Vielen Dank schon einmal an beide Hilfestellungen/Antworten!
So, vielen Dank noch einmal!
Ich hab's (glaube ich) gecheckt, zumindest funktioniert's. Vielen Dank!
Eine Frage habe ich noch: Wenn ich jetzt zwei Quellen zu einem Eintrag habe, erscheinen die Einträge doppelt. Also...
abc
Quelle: Ebay
abc
Quelle: Amazon
anstatt
abc
Quelle: Ebay, Amazon
Wie löse ich das denn? Da stehe ich zur Zeit aufm Schlauch
Hallo,
Eine Frage habe ich noch: Wenn ich jetzt zwei Quellen zu einem Eintrag habe, erscheinen die Einträge doppelt.
ich würde das Ganze etwas anders lösen:
SELECT
t.ID,t.Text,GROUP_CONCAT(q.Quellenname SEPARATOR ', ') as Quellen
FROM
texte t, quellen q, textquellen tq
WHERE
t.ID=tq.textID AND
tq.quellenID=q.QID
GROUP BY
t.ID,t.Text
ich hoffe ich habe da jetzt keinen Denkfehler drinnen aber die Funktion GROUP_CONCAT() erfüllt deinen Zweck meiner Meinung nach sehr gut.
Viele Grüße,
Tim
Hallo Tim,
ich würde das Ganze etwas anders lösen:
was heißt anders. Ein Einsteiger weiß noch nichts von Aggregatsfunktionen und der GROUP-BY-Klausel. Es gibt SQL-Dialekte, da darf man sich GROUP_CONCAT() selbst bauen :-(
Wer übers Einsteigerniveau hinaus ist, verwendet keine impliziten Joins mehr :-)
Also statt:
SELECT
t.ID,t.Text,GROUP_CONCAT(q.Quellenname SEPARATOR ', ') as Quellen
FROM
texte t, quellen q, textquellen tq
WHERE
t.ID=tq.textID AND
tq.quellenID=q.QID
GROUP BY
t.ID,t.Text
~~~sql
SELECT
t.id,
t.text,
[link:http://dev.mysql.com/doc/refman/5.1/en/group-by-functions.html#function_group-concat@title=GROUP_CONCAT](q.Quellenname SEPARATOR ', ') Quellen
FROM
texte t
INNER JOIN
text_quellen tq
ON
t.id = tq.id_text
INNER JOIN
quellen q
ON
tq.id_quelle = q.QID
GROUP BY
t.id,
t.text
AS für Spaltenaliasnamen vermeide ich nur aus Kompatibilitätsgründen :-)
Freundliche Grüße
Vinzenz
Hallo Vinzenz,
in dem Wiki-Artikel
ist mir aufgefallen, dass die Spaltenüberschriften von Name und Vorname vertauscht sind.
Das war schon in dem von Felix oben verlinkten früheren Artikel so und hat offenbar den Umzug ins Wiki unbehelligt überstanden...
Viele Grüße
ottogal
Tach!
in dem Wiki-Artikel
Fortgeschrittene Jointechniken
ist mir aufgefallen, dass die Spaltenüberschriften von Name und Vorname vertauscht sind.
Jetzt nicht mehr.
dedlfix.
Lieber Stoffel,
texte
ID | Text | Quelle1 | abc | 1;2
2 | def | 1;2;3
3 | ghi | 1;3
das ist Quark, da die Spalte Quelle nach Deiner Logik eine beliebig große Menge an ID enthalten kann (durch Semikola getrennt). Nach der Logik relationaler Datenbanken müsstest Du eine n:m-Beziehung mittels einer Zuweisungstabelle machen.
texte
ID | Text
---------
1 | abc
2 | def
quellen
ID | Quellenname
----------------
1 | Amazon
2 | Ebay
3 | Rebuy
text2quelle
Text | Quelle
-------------
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 3
Jetzt kannst Du nach Herzenslust joinen.
Liebe Grüße,
Felix Riesterer.
Und auch wenn dir bereits gesagt wurde, dass Normalisierung bzw. JOINs hier das Mittel der Wahl sind: es gibt noch eine Krücke, die sich hier verwenden lässt: FIND_IN_SET() - die ist bei kleinen Datenmengen OK, aber bei riesigen Datenmengen fürchterlich langsam.