# Tabelle mit "|" getrennten Werten -> einzelnen Wert davon abfragen



## it-girl (27. Mai 2011)

Hallo zusammen,

hab da mal eine Frage...
Also ich wähle zB in meiner JComboBox den Wert "Wert2" aus. Daraus muss ich nun ein SQL-Statement zusammenbauen.
Das Problem daran ist, ich habe in meiner Tabelle sowas hier stehen:

Wert1|Wert2
Wert1|Wert2
Wert2|Wert1|Wert4
Wert1|Wert2
Wert5
Wert1|Wert2
Wert2
Wert4|Wert5
Wert2|Wert1|Wert4
Wert3|Wert5
Wert4|Wert5
Wert5

Wie kann ich das nun machen, dass es nicht nur den alleinstehenden "Wert2" beachtet, sondern auch den in zB "Wert1|Wert2"?

Ich habe diese Tabelle auch in die ComboBox eingelesen, das hat mit dem StringTokenizer ganz gut geklappt. Vielleicht geht das damit ja auch wieder andersrum?

Danke schon mal für eure Antworten.

LG it-girl


----------



## SlaterB (27. Mai 2011)

ich kann mir nicht mal irgendein lustige Variante ausdenken, es ist vollkommen unklar, worum es dir geht,
in einer Combobox wurde "Wert2" ausgewählt, und nun?
was könnte das mit |, mit anderen Einträgen (in der Combobox, in der Datenbank-Tabelle, in beiden?!) zu tun haben, worum geht es?

um doch noch zu raten:
möchtest du alle DB-Einträge laden, die "Wert2" enthalten?
[c]select * from x where y like '%Wert2%'[/c]


----------



## andiv (27. Mai 2011)

Dein Problem ist dass dein Datenbankschema nicht normalisiert ist. Schau dir mal Normalisierung (Datenbank) ? Wikipedia an.


----------



## it-girl (27. Mai 2011)

SlaterB hat gesagt.:


> möchtest du alle DB-Einträge laden, die "Wert2" enthalten?
> [c]select * from x where y like '%Wert2%'[/c]



Ja genau, das möchte ich  Sorry, für mich war der Sinn wohl klar und ich hab das als "selbstverständlich" angesehen...

Das sollte eigentlich auch so funktionieren, aber ich habe ein Leerzeichen in manchen Werten (das mit Wert1|Wert2 war ja nur ein Beispiel). Wie kann ich das behandeln? Das scheint nämlich noch nicht zu klappen.

@ andiv: Ja das weiß ich, aber die DB ist so vorgegeben und ich darf daran nichts ändern.


----------



## SlaterB (27. Mai 2011)

Leerzeichen werden genauso gesucht und gefunden, nenne doch deinen Problemfall ganz konkret,
in SQL geht gewiss noch mehr, aber eine einfache Alternative ist dann noch, alles in Java einzulesen und dort alles mögliche anzustellen 
(nach | splitten, Umwandlung in Kleinbuchstaben, Leerzeichen entfernen)

oder ist das gleich ein Programm mit tausenden Einträgen, wo so etwas nicht praktisch erscheint?


----------



## it-girl (27. Mai 2011)

Also die Tabelle enthält im Moment 624 Einträge, es können aber im Laufe der Zeit mehr werden. Wie performant das dann wird, kann ich leider nicht einschätzen.

Der Teil, in dem ich die ComboBox auslese sieht so aus:

```
ResultSet dt = null;
		List<String> ar = null; // ar, scope und lng werden in Methode getDBLNG initialisiert
		JComboBox lng = null;
		JComboBox scope = null;
		String sqlstr = "";
		if (scope.getItemCount() > 0) {
			//SCOPE enthält Werte der Art "Wert 1|Wert 2|Wert 3" und in der Box steht zB nur "Wert 2"
			sqlstr = "WHERE SCOPE LIKE '%" + scope.getSelectedItem().toString() + "%'";
		}
		// ...
		if (sqlstr != "") {
			lng.removeAllItems();
			dt = db.getDBLNG("SELECT LNG FROM TABLE " + sqlstr
					+ " GROUP BY LNG HAVING Count(LNG)>=1", ar, lng);
		} else {
			lng.removeAllItems();
		}
```


----------



## SlaterB (27. Mai 2011)

falls du noch auf eine Antwort von mir antwortest: Code != Beispiel welches nicht klappt wie gewünscht


----------



## it-girl (27. Mai 2011)

SlaterB hat gesagt.:


> falls du noch auf eine Antwort von mir antwortest: Code != Beispiel welches nicht klappt wie gewünscht


Naja, wie schon gesagt, ich habe eine ComboBox, in der ich die Werte aus der Spalte SCOPE mit dem StringTokenizer nach "|" getrennt und eingefügt habe. Also steht in der Box:

Wert 1
Wert 2
Wert 3
Wert 4
Wert 5

von ehemals diesem in SCOPE:
Wert 1|Wert 2
Wert 1|Wert 2
Wert 2|Wert 1|Wert 4
Wert 1|Wert 2
Wert 5
Wert 1|Wert 2
Wert 2
Wert 4|Wert 5
Wert 2|Wert 1|Wert 4
Wert 3|Wert 5
Wert 4|Wert 5
Wert 5

Nun schreibe ich mir anhand der Box-Auswahl ein SQL-Statement:

```
sqlstr = "WHERE SCOPE LIKE '%" + scope.getSelectedItem().toString() + "%'";
"SELECT LNG FROM TABLE " + sqlstr + " GROUP BY LNG HAVING Count(LNG)>=1"
```

Da nun aber in '%" + scope.getSelectedItem().toString() + "%' ein Wert mit einem Leerzeichen steht, welches Probleme macht, kann die Abfrage nicht ausgeführt werden und es wird kein Wert zurückgegeben, falls in der Box kein Wert steht, der in SCOPE auch mal allein steht. ZB wenn ich "Wert 3" auswähle, bekomme ich kein Ergebnis, weil der Wert in der DB nur in Verbindung mit "Wert 5" dasteht.

Meintest du das mit Beispiel?


----------



## SlaterB (27. Mai 2011)

schau dir dieses toString() genau an, vielleicht gibts vorne oder am Ende noch zusätzliche Leerzeichen, dagegen hilft trim(),
vielleicht ist in der Mitte oder in der DB ein Tab statt eines Leerzeichens,
wenn nicht gar beim toString() komplett was anderes herauskommt als du erwartest, etwa "Klassenname@45a877"

wenn du die DB schnell neu generieren kannst, kannst du testweise _ statt Leerzeichen überall verwenden, in der ComboBox genauso,
oder vergleichbare Dinge machen,
bei mir funktioniert die Suche nach Leerzeichen, aus deinem Code und dem Beispiel kann ich nichts weiter erkennen


----------



## Gast2 (27. Mai 2011)

```
WHERE SCOPE LIKE '%somestring%'
```

Urgs... Das ist so ziemlich das schlechteste was du in einer Datenbank machen kannst. Wenn du eine [c]LIKE[/c] Clause mit einem Wildcard Pattern beginnst kann die Datenbank keinen Index auf der Spalte nutzen. Effektiv machst du bei JEDER Anfrage einen Full Table Scan. Das sollte dir bewusst sein. Wenn die Anwendung größer wird geht deine Performance massiv in den Keller. 

Nebenbei verstehe ich nicht wieso du in einer [c]SCOPE[/c] Spalte mehrer Werte konkateniert hast. Auch das ist nicht im Sinne des (Datenbank) Erfinders. Wenn dich eh nur der erste Wert zur Anzeige interessiert sollte der auch in einer eigenen Spalte stehen.

Du solltest auf jeden Fall dir noch mal gehörig Gedanken über dein Datenbankmodell machen.

Just my 2 cents


----------



## it-girl (27. Mai 2011)

fassy hat gesagt.:


> ```
> WHERE SCOPE LIKE '%somestring%'
> ```
> 
> Urgs... Das ist so ziemlich das schlechteste was du in einer Datenbank machen kannst. Wenn du eine [c]LIKE[/c] Clause mit einem Wildcard Pattern beginnst kann die Datenbank keinen Index auf der Spalte nutzen. Effektiv machst du bei JEDER Anfrage einen Full Table Scan. Das sollte dir bewusst sein. Wenn die Anwendung größer wird geht deine Performance massiv in den Keller.


Habe das auch in Tutorials im Internet immer so gefunden... Wie kann ich das denn besser machen?



fassy hat gesagt.:


> Nebenbei verstehe ich nicht wieso du in einer [c]SCOPE[/c] Spalte mehrer Werte konkateniert hast. Auch das ist nicht im Sinne des (Datenbank) Erfinders. Wenn dich eh nur der erste Wert zur Anzeige interessiert sollte der auch in einer eigenen Spalte stehen.
> 
> Du solltest auf jeden Fall dir noch mal gehörig Gedanken über dein Datenbankmodell machen.


Wie ich schon gesagt habe, ist die DB so vorgegeben und ich kann und darf daran nichts ändern. Der, der die DB erstellt hat, ist der Meinung, dass es besser so ist, als für alles eine eigene Tabelle zu erstellen. Ich persönlich finde es so auch grässlich, habe das auch anders gelernt. Deshalb habe ich keine Ahnung, wie ich das wieder auseinander kriege, da ich das ja noch nie machen musste und auch hoffentlich nie wieder machen muss... :autsch:
Und mein Beispiel sollte nicht heißen, dass ich "immer nur" den ersten Wert brauche. Er könnte auch an 2. oder 3. Stelle stehen, der Wert muss auf jeden Fall dabei sein - egal an welcher Stelle.

LG it-girl


----------



## it-girl (27. Mai 2011)

SlaterB hat gesagt.:


> schau dir dieses toString() genau an, vielleicht gibts vorne oder am Ende noch zusätzliche Leerzeichen, dagegen hilft trim(),
> vielleicht ist in der Mitte oder in der DB ein Tab statt eines Leerzeichens,
> wenn nicht gar beim toString() komplett was anderes herauskommt als du erwartest, etwa "Klassenname@45a877"
> 
> ...


ich hab grad nachgeschaut, ich habe weder Tabs noch zusätzliche Leerzeichen, noch sonst irgendwas drin, was da nicht hingehört. Und ich bekomme auch kein "Klassenname@45a877" zurück, sondern wirklich den Wert der ComboBox als String,wie ich ihn ausgewählt habe, also wenn ich "Wert 2" auswähle, bekomme ich mit scope.getSelectedItem().toString() auch wieder "Wert 2" zurück.


----------



## ARadauer (27. Mai 2011)

Zum Thema Performance... es kommt auf die Datenmenge drauf an. Wird sie größer muss man sich echt was überlegen. zb denormalisieren oder seperat mit zb solr indizieren und dort suchen.

Wie groß sie werden kann, bis die performance ein problem darstellt? Ich würds einfach ausprobieren...


----------



## SlaterB (27. Mai 2011)

> kann die Abfrage nicht ausgeführt werden und es wird kein Wert zurückgegeben
gibts eigentlich eine Fehlermeldung?

ich habe mir jetzt noch die Query angesehen, du gruppierst ja nach LNG, wo anscheinend die Werte drinstehen,
dir ist bewußt dass da jede Kombination für sich einzeln gezählt wird, wenn du etwa nach Wert 3 suchst und in der DB
Wert 3|Wert 5
sowie 
Wert 3
steht, dann gibt es das jeweils nur einmal, beide kommen nicht durch die Bedingung "HAVING Count(LNG)>=1" durch, hast du das bedacht?
vielleicht einfach nur count(*) zählen wenn dich die Anzahl aller Einträge mit 'Wert 3' drin interessiert

allein hinsichtlich LIKE mit Leerzeichen:
generell solltest du erstmal einfacher arbeiten, ohne GROUP BY, am besten auch ohne ComboBox, funktioniert die Query
[sql]SELECT * FROM TABLE WHERE SCOPE LIKE '%Wert 3%'[/sql]
?
liefert sie keine Ergebnisse oder genau die richtigen?


----------



## Michael... (27. Mai 2011)

Grundsätzlich hiflt bei solchen Problemen:
1. Das SQL Statement auf der Konsole oder sonst wo ausgeben.
2. Schaut es korrekt aus, dann das Statement direkt auf der Datenbank ausführen.
3. Funktioniert es nicht oder kommt ein falsches Ergebnis. Das Statement in der DB Umgebung solange korrigiern bis es wie gewünscht läuft.
4. Das funktionierende Statement ins Java Programm übertragen.


----------



## it-girl (27. Mai 2011)

Kommando zurück, ich habe den "Fehler" gefunden... Zu der Abfrage, die ich gemacht habe, gab es wirklich kein Ergebnis. Habe das nun von Hand in der DB nachgeschaut.

Also mit dem 
	
	
	
	





```
SELECT * FROM TABLE WHERE SCOPE LIKE '%Wert 3%';
```
 klappt 

Danke euch! 

LG it-girl


----------

