(My)SQL: Suche In über mehrere Rows verteilte Daten
Geizhals » Forum » Programmierung » (My)SQL: Suche In über mehrere Rows verteilte Daten (26 Beiträge, 522 Mal gelesen) Top-100 | Fresh-100
Du bist nicht angemeldet. [ Login/Registrieren ]
.
Re: (My)SQL: Suche In über mehrere Rows verteilte Daten
18.09.2010, 07:54:24
Löse es nicht so |-D.

Du könntest Dich schon spielen... In der PostgreSQL könnte man es wie folgt machen:

(1) Zuerst mal relevantes rauspicken:

SELECT user, field FROM xyz
WHERE (field = 2 AND data="23") OR (field=10 and data="40") or ....

Dadurch hast mal alle relevanten Bedingungen.

(2) Angenommen, derzeit wären in Summe 5 Bedingungen aktuell (also 5 Klammerausdrücke), dann kannst wie folgt filtern:


SELECT user from
(SELECT user from user_data
    where (feld=1 and wert=1)
    or (feld=2 and wert=30))
    or (feld=7 and ....)
    ....
    ....
  as bubu2
  group by user
  having count(*)=5 ;


Es klappt also in einem einzigen SQL-Statement, das noch dazu leicht gebaut ist.
Zusätzlich zu dem join(") or (", @bedingungen) musst nur ein
"having count(*)=" . scalar(@bedingungen)
dranpappen.

Aber ich wiederhole:
DU WILLST DAS NICHT |-D

Zur Performance:
Das performt zwar pfeilschnell - du hast maximal 100'000 Zeilen, real wahrscheinlich unter 1000, in der Subquery, darüber lacht eine Datenbank nicht einmal. 1000 Zeilen werden wahrscheinlich unter 50k RAM brauchen - also auch nichts.

AABER:
- alle Zugriffskonstruktionen werden umständlich.
- Es trägt nicht zur Lesbarkeit der DB bei
- Ideen, auf die man selbst nicht kommt, soll man nicht verwenden |-D, weil:

Debuggen ist doppelt so schwer wie entwickeln. Wenn Du beim Entwickeln etwas "gerade noch" hinbekommst, hast etwas nicht-debugbares erschaffen |-D


Und _wenn_ du schon absurde Sachen machen willst - warum in der MySQL und nicht PostgreSQL ????

18.09.2010, 08:02 Uhr - Editiert von kombipaket, alte Version: hier
Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
.
Re: (My)SQL: Suche In über mehrere Rows verteilte Daten
18.09.2010, 23:17:01
Eine Lösung, die ich inzwischen gefunden (habe wohl schon zu lange nimmer mit Datenbanken gearbeitet, da ich nicht gleich an Sub-Selects gedacht habe) habe und die alles in einem Statement löst wäre folgende:

SELECT user FROM user_data WHERE field = 5 AND data = "2010" AND user IN 
 (SELECT user FROM user_data WHERE field = 2 AND data = "23" AND user IN 
   (SELECT user FROM user_data WHERE field = ... usw. usw)
 );


Im Prinzip macht das genau das, was mein als erster vorgeschlagener Ablauf machen würde, nur dass sich eben die Datenbank um's Zusammenfügen der IDs kümmert. Aber wenn auf 20 Felder gleichzeitig geprüft wird, ist ein Statement mit 20 ineinander geschachtelten Selects sicher nicht das wahre.

Weiteres Lesen hat aber ergeben, dass ich das definitiv nicht machen will. MySQL ist bei Sub-Queries recht ineffizient, wobei das oben genau der Worst-Case (sogar laut MySQL-Doku) ist.

In dem Fall scheint es tatsächlich schneller zu sein, das über die (Pseudo;-))-Programmiersprache zu lösen.

user_where = '';
foreach (_feld,_wert) aus (suchfelder,suchwerte) {
   user_ids = query('SELECT user FROM user_data WHERE field = _feld AND data = _wert' + user_where);
   if (count(user_ids) > 0) {
      user_where = ' AND user IN (' + join(',', user_ids) + ')';
   } else {
      // keine Benutzer mehr im Ergebnis -> abbrechen
      last;
   }
}

// user_ids enthält hier die Liste aller den Such-Kriterien
// entsprechenden Benutzer; kann auch leer sein


Mit jedem Durchgang ist die Liste der user_ids eine Untermenge des vorherigen Durchgangs, bis entweder alle Felder abgearbeitet wurden oder gar keine Benutzer mehr übrig bleiben (weil keiner die geforderten Kriterien erfüllt).

Das scheint mir hier die beste Lösung zu sein, da ja auch die Anzahl der zu überprüfenden Felder variabel sein kann.

Antworten PM Übersicht Chronologisch Zum Vorgänger
 
Melden nicht möglich
 

Dieses Forum ist eine frei zugängliche Diskussionsplattform.
Der Betreiber übernimmt keine Verantwortung für den Inhalt der Beiträge und behält sich das Recht vor, Beiträge mit rechtswidrigem oder anstößigem Inhalt zu löschen.
Datenschutzerklärung