Übereinstimmungen von Listenwerten in SQL

Ronald Nickel

Legendäres Mitglied
Hallo an alle Ayomisten
und wieder schaue ich in meine SQL-Bücher wie ein Schwein ins Uhrwerk. (Nix raff)

Aufgabe:
Ein Datenbankfeld der Tabelle A enthält eine kommaseparierte Liste:"1,2,3,4,11,9,"
Tabelle B enthält ebenfalls ein ähnliches Feld mit den Inhalten: "2,7,13,56,678"

gewünschtes Statement:
Gib alle Datensätze von Tabelle A aus, die mindestens eine Übereinstimmung der Zahlen in den besagten Feld hat (in diesem Fall die "2")
Wichtig ist das es sich bei tabelle B nicht zwingend um ein tabelle handeln muss sondern auch um eine Variable. Ich habe hier nur Tabelle B exemplarisch verwendet.

Mit LIKE geht das wohl nicht da LIKE bei "1" und "11" einen WAHR ergeben würde

Set MxVar ="2,7,13,56,678"
select * from Tabelle A where MyVar .... ????

Hat mir da jemand ne Idee?

Gruß Ronny
 
QUOTE (Ronald Nickel @ Di 12.06.2007, 14:12)Mit LIKE geht das wohl nicht da LIKE bei "1" und "11" einen WAHR ergeben würde

Set MxVar ="2,7,13,56,678"
select * from Tabelle A where MyVar .... ????

Mit solchen hässlichen Sachen hab ich mich mal im Zusammenhang mit Typo3 herumgeschlagen, wo 1:n Beziehungen oft in kommaseparierten BLOB-Feldern gespeichert werden (grauenhaft, wenn man die Daten noch mit Queries weiterverarbeiten möchte).

Es läuft dann darauf hinaus, dass du ein Statement mit mehreren OR-verknüpften Bedinungen erstellen musst:

select * from Tabelle A where MyVar LIKE '1,%' or MyVar LIKE '%,1,%' or MyVar LIKE '%,1';

Wie gesagt, halte ich einen solchen Ansatz für ungeeignet und du solltest es vermeiden, deine DB überhaupt so aufzubauen (wenn du darauf überhaupt Einfluss hast).
 
Es gibt noch das IN-Statement. Mit dem kann man prüfen, ob ein gegebener Wert in einer Liste von Werten vorkommt. Beispiel

Select * from TabelleA where TabelleA.FeldA IN (2,7,13,56,678)

Aber dazu muss das FeldA normalisiert sein, resp. es darf keine kommaseparierte Liste sein. Geht für Deinen Fall also nicht.

Ich schliesse mich da Polonius an: normalisier die Daten. Und wenn Du darauf keinen Einfluss hast, dann sags dem Zuständigen ;-)

Griessli
Irene

 
Sql ist leistungsfähig, wenn die Daten in den Tabellen normalisiert sind.

Diese Daten sind nicht normalisiert, da die erste Normalform verletzt ist - mehrere Atome stehen, kommagetrennt, in einer Zelle. Also muß Sql völlig scheitern.

Es ist allerdings möglich, normalisierte Daten gegen einen nicht normalisierten Input abzugleichen:

Die Daten 1,2,3,4,11,9 gehören, zusammen mit der ID des Hauptdatensatzes, als sechs Zeilen in eine dreispaltige Detailtabelle.

id | hauptId | detailId

Dann kann man das mit

QUOTE Select *
From Detailtabelle
Where HauptId = 'Hauptwert' And
CharIndex(',' + detailId + ',',
',' + @Eingabezeichenfolge + ',') > 0


auswerten: Die DetailId mit Kommas ergänzen und testen, ob diese kurze Zeichenfolge in der langen, ebenfalls mit Kommas berandeten Zeichenfolge drin ist.

Bei zwei Tabellen reicht natürlich ein einfacher Inner Join.
tongue.gif


PS: Wenn Typo3 so Werte speichert, dann ist das gruselig
mad.gif
- oder peinlich für die Entwickler
biggrin.gif


PS: @Irene, deine Lösung bedeutet, daß der Sql-Befehl zur Laufzeit zusammengebaut wird. Die obige hat den Vorteil, daß sie auch innerhalb einer gespeicherten Prozedur funktioniert - und damit alle Probleme mit Sql-Injektionen umgeht.
 
Erst mal vielen dank für alle antworten. Ich sehe schon dass das weider neknifflige sache wird. Die kommaseparierte Liste erhalte ich durch ein "muliple" Select form. Der User hat also beispielsweise eine Liste Interessen ausgewählt die mit option value als Nummerischer Wert deklariert werden. Nu soll ein anderer User anhand seiner eigenen "Ineressenliste" einen Seelenverwandten User herausfinden der mindestens eine Übereinstimmung (Zahlenwert) mit der eigenen Liste hat. Die Kommaseparierten Listen müssen also in EINEM DB-Feld stehen. Leider ist auch die Länge der Liste beider User variabel.

Gruß Ronny
 
QUOTE (Ronald Nickel @ Di 12.06.2007, 16:39)Ich sehe schon dass das weider neknifflige sache wird.

Nö, dann ist es doch völlig harmlos.

Du setzt die Tabellen ordentlich normalisiert an - siehe oben für die Verknüpfungstabelle.

Wenn eine Zeichenfolge '2,3,5,7' kommt, dann füllst Du aus dieser nach dem obigen Prinzip mit einem Insert-Befehl die Detailtabelle mit den Verknüpfungen zu diesem Nutzer. Mit einem zweiten, analogen Delete löschst Du alle, die in der aktuellen Zeichenfolge fehlen, aber vielleicht aus einem früheren Eintrag noch drinstehen.

Und dann gibt es eine einzige normalisierte Tabelle, die mit sich selbst verknüpft die Übereinstimmungen zwischen zwei Nutzern liefert.
 
Zurück
Oben