Antwort
 
LinkBack Themen-Optionen Thema durchsuchen
Alt 18.04.2009, 15:46 Nach oben    #1
Erfahrener Benutzer
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 314
Standard MySQL-Select mit LIKE - Operator - Problem

Hallo liebe Entwicklergemeinde,

meine Tabelle sieht schematisch so aus:

ID, Name, Adresse, Nummer

Name und Adresse können doppelt vorkommen, das ist auch erwünscht. Auch Nummern können doppelt vorkommen, lediglich die ID ist und bleibt eindeutig.

Ich habe z.B. eine Abfrage wie diese:

Code:
SELECT Name FROM Table WHERE Name LIKE '%$suchstring%'
Ich möchte, dass, wenn eine Datenzeile auf die WHERE-Bedingung anspricht, automatisch alle anderen Datenzeilen, die die selbe Nummer haben, nicht mehr auf die WHERE-Bedingung hin überprüft werden, aber ausgeliefert werden.
Genausogut könnte die WHERE-Bedingung dann auch automatisch erweitert werden.

Also noch während MySQL sucht:

SELECT Name FROM Table WHERE Name = '(gefundene Nummer)' OR LIKE '%suchstring%'

Ist das möglich?

Und eine andere Frage ist:
Wenn ich eine SELECT-Abfrage starte, ist es möglich festzulegen, dass Worte vorkommen können, aber nicht müssen?

Ich stelle mir das so vor:
Code:
SELECT Name FROM Table WHERE Name LIKE '%$suchstring1%' AND adresse LIKE '%suchstring2%'
Alle Datensätze, auf die die Suchstring2 - Bedingung UND die Suchstring1 zutreffen, sollen vor den Datensätzen zurückgegeben werden, auf die nur die Suchstring1 - Bedingung zutrifft. Die Suchstring1 - Bedingung MUSS aber zutreffen.

Wie kann ich MySQL sagen, dass etwas vorkommen KANN, aber nicht MUSS, und wenn es vorkommt, es als erstes zurückgegeben werden soll?

Danke für Anregungen, Feedback und gerne auch Referenzen zum selbst erlernen!

Geändert von Sekundentakt (18.04.2009 um 17:24 Uhr)
Sekundentakt ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 18.04.2009, 21:06 Nach oben    #2
Sesselkleber
 
Benutzerbild von sparrow
 
Registriert seit: 17.01.2005
Beiträge: 626
Standard

Zu deinem ersten Problem:

Code:
SELECT * FROM `Test`
ID 	Name 	Adresse 	Nummer
1 	Name1 	Adresse1 	1
2 	Name2 	Adresse2 	1
3 	Name3 	Adresse3 	2
4 	Name4 	Adresse4 	2
Code:
SELECT * FROM `Test` WHERE `Nummer` IN (SELECT ID FROM `Test` WHERE `Name` LIKE "%ame1%")
ID 	Name 	Adresse 	Nummer
1 	Name1 	Adresse1 	1
2 	Name2 	Adresse2 	1

Zitat:
Zitat von Sekundentakt
Wenn ich eine SELECT-Abfrage starte, ist es möglich festzulegen, dass Worte vorkommen können, aber nicht müssen?
Ja, schränk die Suche nicht ein. Dann KÖNNEN alle Wörter vorkommen, MÜSSEN aber nicht.
Anders ausgedrückt: Die von dir gestellte Bedingung trifft auf ALLE Datensätze zu. Das klingt nach regulären Ausdrücken und macht hier wenig Sinn.

Zitat:
Zitat von Sekundentakt
Alle Datensätze, auf die die Suchstring2 - Bedingung UND die Suchstring1 zutreffen, sollen vor den Datensätzen zurückgegeben werden, auf die nur die Suchstring1 - Bedingung zutrifft. Die Suchstring1 - Bedingung MUSS aber zutreffen.
In einer Abfrage geht das Sortieren wie du es benötigst nicht. Du kannst allerdings das Ergebnis von 2 Ausgaben mit dem Schlüsselwort UNION verbinden.
Code:
SELECT a FROM table_a 
UNION 
SELECT b FROM table_b

Gruß
Sparrow
sparrow ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 18.04.2009, 22:01 Nach oben    #3
Erfahrener Benutzer
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 314
Standard

Hi Sparrow,

die erste Lösung werde ich mir mal genauer anschauen, vielen Dank.

EDIT:
Ist das * der äußeren Abfrage notwendig, bzw. muss die Spalte, die in der inneren Bedingung angesprochen wird in der äußeren Bedingung ebenfalls angesprochen werden?

EDIT2:
Die Resultate der inneren Abfrage bilden ja die WHERE-Bedingung - wie wird das verknüpft? Das MySQL-Manual gibt mir darauf keine direkte Antwort.
Mal angenommen ich will von der inneren Abfrage keine IDs (Primärschlüssel), sondern meinetwegen Namen zurückgeliefert, die auch mehrfach in der Tabelle der äußeren Abfrage vorkommen.
Wird das dann mit AND oder OR verknüpft? Oder ist das gar nicht vergleichbar mit diesen Operatoren? Kann man die Verknüpfung in solchen Fällen nach der Art und Weise auch beeinflussen?


Zitat:
In einer Abfrage geht das Sortieren wie du es benötigst nicht. Du kannst allerdings das Ergebnis von 2 Ausgaben mit dem Schlüsselwort UNION verbinden.
Geh ich richtig in der Annahme, dass die Ergebnisse einfach aneinander angehängt werden?

Zitat:
Ja, schränk die Suche nicht ein. Dann KÖNNEN alle Wörter vorkommen, MÜSSEN aber nicht.
Anders ausgedrückt: Die von dir gestellte Bedingung trifft auf ALLE Datensätze zu. Das klingt nach regulären Ausdrücken und macht hier wenig Sinn.
Ich glaub da haben wir uns missverstanden.
Relevante Daten sind alle Daten, die auf die Suchstring1-Bedingung zutreffen. Am relevantesten sind allerdings die Daten, die AUCH auf die Suchstring2-Bedingung zutreffen. Diese Ergebnisse sollen als erste ausgegeben werden.
Über UNION wird das denke ich nichts.

Vielen Dank für deine Hilfe!
Gruß

Geändert von Sekundentakt (18.04.2009 um 23:32 Uhr)
Sekundentakt ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 19.04.2009, 02:49 Nach oben    #4
Oliver O.
 
Benutzerbild von Xean
 
Registriert seit: 17.08.2005
Beiträge: 475
Standard

Hallo Sekundentakt,

für Edit1:
Das * ist nicht notwenig. Sparrow hat es (so würde ich vermuiten) genutzt, um eine schöne ausgabe zu bekommen. Stattdessen kann man auch nur bestimmte felder benutzen.

für Edit2:
Ich finde Sparrows zweiten Query bisschen eigenartig. Nach meinem Verständniss sollte nur die Zeile mit der ID 1 raus kommen, aber das ist eigentlich egal.
Du kannst in dem Inneren Select auch ndere Werte zurückgeben lassen. Wichtig hier ist, dass es nur eine Spalte sein darf, da er das Ergebniss des inneren Selects mit der anweisung des äußeren vergleicht.
Das innere Select funktioniert wie ein eigenständiges Select, und kann in dem WHERE-Teil weitere Bedingungen haben, die mit AND oder OR verknüpft werden. Auch weitere innere Selects sind möglich. Die Rückgabewerte des Inneren Selects haben aber nichts mit den Rückgabewerten des Äußeren Selects zu tun. Naja, eigentlich schon; es kommt drauf an, wie man die Ausgaben des Inneren Selects verarbeitet, aber die Ausgaben der beiden Selects werden nicht zusammen geworfen.

Für die Sortierung:
Zwar hatte ich so etwas noch nie, aber ich hab bisschen mit dem phpMyAdmin-SQL-Befehl-Editor gespielt, und herrausgefunden, dass mySQL sowas hier zuläst:

Code:
SELECT * FROM `Test` WHERE `Name` LIKE `%suchstring1%` ORDER BY `adresse` LIKE '%suchstring2%' DESC
Beim drüber nachdenken ist es ja klar. Bei dem vergleich (`adresse` LIKE '%suchstring2%') kommt ja entweder TRUE oder FALSE raus, und dass kann man benutzen zum sotieren... keine ahnung, ob das die feine englische Art ist, aber bei den kleinem Test bei mir hats funktioniert.

Ich hoffe, ich konnte dir weiter helfen!

Xean
__________________
"Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, der wird am Ende beides verlieren" (Benjamin Franklin)
Xean ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 19.04.2009, 11:16 Nach oben    #5
Erfahrener Benutzer
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 314
Standard

Hi Xean,

danke für deine noch so späte Antwort!

Edit 1 habe ich dann jetzt verstanden.

Ich glaube aber, dass du meine Frage in EDIT2 falsch verstanden hast.

Mir ist schon klar, dass ich nur eine einzige Spalte für den Vergleich verwenden kann. Mich würde jetzt aber interessieren, wie die Resultate der inneren Abfrage verknüpft werden. Also stell dir mal vor, Sparrows Query würde so aussehen:
Code:
SELECT * FROM `Test` WHERE `Nummer` IN (SELECT ID FROM `Test` WHERE `Name` LIKE "%name%")
Dann würden insgesamt 4 IDs zurückgegeben werden.

Heißt das, dass die äußere Abfrage quasi sagt:
Code:
SELECT * FROM `Test`WHERE `Nummer` in den Datenzeilen mit den IDs 1,2,3,4
oder wie?

Was wäre denn, wenn die innere Abfrage keine Datenzeilen-IDs liefern würde, sondern ebenfalls Namen? Ist sowas dann überhaupt brauchbar, wenn diese Namen keine Primärschlüsselfunktion hätten?
Oder würde das dann - vom Verständnis her - so aussehen:

Code:
SELECT * FROM `Test`WHERE `Nummer` in den Datenzeilen mit den `Name`-Werten Simone, Maria, Thomas, Nils
?

Und wenn es so wäre, wie ichs gerade sinngemäß formuliert habe, dann würde die Verknüpfung von Simone, Maria, Thomas, Nils immer mit einem OR geschehen?
Also würde der Query quasi genau der selbe sein, wie wenn ich, würde ich vorher wissen, welche Namen zurückgeliefert würden, das hier schreibe:


Code:
SELECT * FROM `Test`WHERE `Nummer` = `Simone` OR `Nummer` = `Maria` usw. usf.
Vorraussetzung dafür wäre natürlich, dass Nummer auch tatsächlich Namen und keine Nummern enthält.

Zu deiner Sortieridee - die finde ich sehr interessant.
Die werde ich mir in jedem Falle zwischenmerken, um zu sehen, ob die auch noch bei größeren Datenmengen fehlerfrei bleibt.

Danke für deine Mühen!
Sekundentakt ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 19.04.2009, 12:36 Nach oben    #6
Sesselkleber
 
Benutzerbild von sparrow
 
Registriert seit: 17.01.2005
Beiträge: 626
Standard

Hallo Sekundentakt,

wir trennen uns kurz mal von der Sache mit dem Union und konzentrieren uns auf die von mir oben gezeigte Abfrage.
Erstmal vorweg: die gezeigte Abfrage bringt das Resultat was du dir wünscht, richtig?

So, was wir dort verwenden ist eine sogenannte Subquery, sieh das ganze als 2 getrennte Abfragen.

Zuerst die äußere Abfrage:
SELECT * FROM test WHERE nr IN (1, 2, 3, 4)
Diese Abfrage würde dir alle Felder aller Datensätze aus der Tabelle "test" liefern die in der Spante "nr" entweder den Wert 1 ODER 2 ODER 3 ODER 4 haben.

SELECT id FROM test WHERE name LIKE "%irgendwas%"
Diese Abfrage würde dir die Spalte "id" aller Datensätze in "test" liefern deren Spalte "name" eine String mit dem Teilstring "irgendwas" enthält.

Mit einer Subquery kannst du das Ergebnis der einen Abfrage als Bedingung der anderen Abfrage verwenden.
SELECT * FROM test WHERE nr IN (SELECT id FROM test WHERE name LIKE "%irgendwas%")
Diese Abfrage liefert dir alle Spalten der Tabelle "test" deren Wert in der Spalte "nr" gleicher einem Ergebnis der Subquery ist.

Und ob das auch mit Texten geht?
Das kannst du ja jetzt einfach selber ausprobieren. Dazu brauchst du nicht einmal eine Subquery. Du könntest versuchen ob IN auch mit Zeichenketten arbeiten kann.

Gruß
Sparrow

Geändert von sparrow (19.04.2009 um 12:42 Uhr)
sparrow ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 19.04.2009, 14:23 Nach oben    #7
Erfahrener Benutzer
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 314
Standard

Zitat:
wir trennen uns kurz mal von der Sache mit dem Union und konzentrieren uns auf die von mir oben gezeigte Abfrage.
Erstmal vorweg: die gezeigte Abfrage bringt das Resultat was du dir wünscht, richtig?
So wies aussieht, liefert mir das genau das Resultat, was ich mir gewünscht habe :)

Unklar ist mir allerdings, ob bei 6mio Datensätzen (beide Subquerys beziehen sich auf ein und die selbe 6mio-Tabelle) diese jeweils 2x durchgegangen werden, oder ob nicht zutreffende, bei einem Index auf Nummer und ID, einfach übersprungen werden - weißt du was dazu?
Hast du vielleicht sogar irgendwelche Referenzen, auf denen man nachlesen kann, wie bei Tabellen die mit Subquerys angezapft werden, am besten mit Indexen gearbeitet wird?

Zitat:
Zuerst die äußere Abfrage:
SELECT * FROM test WHERE nr IN (1, 2, 3, 4)
Diese Abfrage würde dir alle Felder aller Datensätze aus der Tabelle "test" liefern die in der Spante "nr" entweder den Wert 1 ODER 2 ODER 3 ODER 4 haben.

SELECT id FROM test WHERE name LIKE "%irgendwas%"
Diese Abfrage würde dir die Spalte "id" aller Datensätze in "test" liefern deren Spalte "name" eine String mit dem Teilstring "irgendwas" enthält.

Mit einer Subquery kannst du das Ergebnis der einen Abfrage als Bedingung der anderen Abfrage verwenden.
SELECT * FROM test WHERE nr IN (SELECT id FROM test WHERE name LIKE "%irgendwas%")
Diese Abfrage liefert dir alle Spalten der Tabelle "test" deren Wert in der Spalte "nr" gleicher einem Ergebnis der Subquery ist.
Okay, genau so habe ich das auch verstanden. Danke!

Funktioniert so ein Subquery eigentlich auch bei Funktionen?
Also wenn die Funktion jetzt so aussehen würde:
"irgendwas" MATCHT (hier drinne steht der Subquery)
Werden dann die Subqueryresultate als einzelne Argumente behandelt oder in ihrer Gesamtheit oder ist das immer wieder unterschiedlich?
Ich habe jetzt keine Funktion parat, die genau das machen würde, es geht mir aber ums Prinzip, ob das so funktionieren kann.

Ich bedanke mich in jedem Falle für deine Mühe - das hat mir sehr weitergeholfen!

Liebe Grüße und einen schönen Sonntag
Sekundentakt
Sekundentakt ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 19.04.2009, 14:42 Nach oben    #8
Sesselkleber
 
Benutzerbild von sparrow
 
Registriert seit: 17.01.2005
Beiträge: 626
Standard

Zitat:
Zitat von Sekundentakt Beitrag anzeigen
Unklar ist mir allerdings, ob bei 6mio Datensätzen (beide Subquerys beziehen sich auf ein und die selbe 6mio-Tabelle) diese jeweils 2x durchgegangen werden, oder ob nicht zutreffende, bei einem Index auf Nummer und ID, einfach übersprungen werden - weißt du was dazu?
Ich arbeite wegen der Lizenz und der umständlichen Handhabung von Transaktionen nur bei kleinen Projekten, wenn überhaupt, mit mySQL, daher kann ich dazu nicht soviel sagen.
Beide Abfragen werden auf jeden Fall getrennt durchgeführt, ich denke nicht, dass der Planer da im Hintegrund nur eine Abfrage draus baut.
Wenn es mySQL genauso macht wie andere Datenbanken sieht es in etwa so aus:
Für die Subquery in dem Beispiel müssen auf jeden Fall alle Datensätze sequenziell durchlaufen werden, da du nach einem Teil Teilstring suchst. Da gibt es keinen entsprechenden Index für. Das kostet auf jeden Fall ordentlich Zeit, was aber, soviel ich weiß, in der Natur der Sache liegt.
Für die äußere Abfrage sollte, falls diese öfter ausgeführt wird, auf jeden Fall ein entsprechender Index auf Nummer angelegt werden.

Bei deinen restlichen Fragen kann ich leider nicht weiterhelfen. Die sind sehr mySQL-lastig.


Gruß
Sparrow
sparrow ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 19.04.2009, 15:06 Nach oben    #9
Erfahrener Benutzer
 
Registriert seit: 16.08.2008
Ort: Mecklenburg-Vorpommern
Beiträge: 314
Standard

Zitat:
Für die Subquery in dem Beispiel müssen auf jeden Fall alle Datensätze sequenziell durchlaufen werden, da du nach einem Teil Teilstring suchst. Da gibt es keinen entsprechenden Index für. Das kostet auf jeden Fall ordentlich Zeit, was aber, soviel ich weiß, in der Natur der Sache liegt.
Vielleicht setze ich auch statt auf LIKE auf eine Volltextsuche (darum Index), das wird aber noch entschieden, da ich mit Volltextsuchen keine Erfahrungen habe.
Teilworte werden in diesem schematischen Beispiel gesucht. In der Praxis gehts aber um ganze Worte :)

Zitat:
Bei deinen restlichen Fragen kann ich leider nicht weiterhelfen. Die sind sehr mySQL-lastig.
Trotzdem vielen Dank.
Sekundentakt ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
MySQL RegExp nächste Zeile Sekundentakt Datenbanken 1 07.03.2009 15:45
[Server] LAMPP mit ftp, openSSL, msmtp, webalizer und phpmyadmin in einer chroot Jann Hendrik Tutorials 4 24.02.2009 14:55
Your most abnormal Query Guradia Datenbanken 21 19.04.2006 00:15
MySQL 5.1 kommt in die Beta-Phase Ben Nachrichten 1 02.03.2006 14:31
[SQL] Zufallsdatensatz auslesen - MySQL 3.23 Ben Tutorials 0 16.03.2005 00:06


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:40 Uhr.


Powered by vBulletin® Version 3.8.4 (Deutsch)
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47