Thomas: Schachtelungstiefe von "IN" - oder Optimierung?

Hallo,

ich habe folgendes Problem: Für registrierte Nutzer existiert ein Kriterienkatalog, der 83 Punkte umfasst. Abgelegt sind diese in einer Tabelle mit 2 Spalten: Die NutzerID und jeweils ein Kriterium. D.h., wer alle 83 Punkte erfüllt hat auch 83 Zeilen in der Tabelle (Nein, das Design stammt nicht von mir).

Um jetzt einen Nutzer rauszusuchen, der viele Kriterien erfüllt, nutze ich bisher ein Konstrukt dieser Art:

SELECT questanscode FROM Activity_domains where (refcode = '1.1' and questanscode in ( SELECT questanscode FROM Activity_domains WHERE refcode = '1.2' and questanscode in ( SELECT questanscode FROM Activity_domains WHERE refcode = '1.3' and questanscode in ( SELECT questanscode FROM Activity_domains WHERE refcode = '1.4'))))

Ist natürlich nicht das schönste Teil, aber es war die erste funktionierende Lösung überhaupt. Leider streckt die Access-DB die Waffen, wenn mehr als 50 Kriterien abgefragt werden sollen.

Da ich an der DB nichts ändern kann/darf meine Frage: Hat jemand eine Idee, wie man es besser lösen könnte? Der SQL-String muß lediglich halbwegs vernünftig per PHP-Script erzeugbar sein...

Danke & Gruß

Thomas

  1. Hi,

    Abgelegt sind diese in einer Tabelle mit 2 Spalten: Die NutzerID und jeweils ein Kriterium. D.h., wer alle 83 Punkte erfüllt hat auch 83 Zeilen in der Tabelle (Nein, das Design stammt nicht von mir).

    sehr anständig von Dir, dass Du Dich nicht mit fremden Federn schmücken willst. Andere hätten diese glückliche Situation vielleicht ausgenutzt.

    Um jetzt einen Nutzer rauszusuchen, der viele Kriterien erfüllt,

    Also viele Datensätze in der Tabelle hat? Ein COUNT(*), ein GROUP BY, ein ORDER BY, und fertig ist die Laube.

    SELECT questanscode FROM Activity_domains where (refcode = '1.1' [...]

    Welche Bedeutung hat refcode? Was steht in den anderen Spalten? Wo ist die NutzerID? Gibt es Verknüpfungen zu anderen Tabellen, die von Relevanz sind?

    Da ich an der DB nichts ändern kann/darf

    Warum solltest Du auch? :-)

    meine Frage: Hat jemand eine Idee, wie man es besser lösen könnte?

    Mir ist das DB-Layout nicht genügend bekannt, die Inhalte auch nur bedingt, und leider vergaßt Du zu erwähnen, wie Dein Wunsch-Resultset aussieht. Mit diesen Informationen könnte sicherlich jemand noch spezifischer antworten.

    Cheatah

    1. Hallo,

      Hi,

      Abgelegt sind diese in einer Tabelle mit 2 Spalten: Die NutzerID und jeweils ein Kriterium. D.h., wer alle 83 Punkte erfüllt hat auch 83 Zeilen in der Tabelle (Nein, das Design stammt nicht von mir).
      sehr anständig von Dir, dass Du Dich nicht mit fremden Federn schmücken willst. Andere hätten diese glückliche Situation vielleicht ausgenutzt.
      Um jetzt einen Nutzer rauszusuchen, der viele Kriterien erfüllt,
      Also wie viele Datensätze in der Tabelle hat? Ein COUNT(*), ein GROUP BY, ein ORDER BY, und fertig ist die Laube.

      Leider nicht ganz so trivial: Welche Nutzer erfüllen Kriterium 1,10,60,61,62,...?

      SELECT questanscode FROM Activity_domains where (refcode = '1.1' [...]
      Welche Bedeutung hat refcode? Was steht in den anderen Spalten? Wo ist die NutzerID? Gibt es Verknüpfungen zu anderen Tabellen, die von Relevanz sind?

      Ooops, sorry. der refcode ist jeweils das Kriterium; questanscode ist die NutzerID. Letzteres Feld ist mit einer Tabelle verknüpft, die die Nutzerdaten enthält.

      Da ich an der DB nichts ändern kann/darf
      Warum solltest Du auch? :-)

      In den nächsten Jahren wird sehr sicher an den Kriterien nicht rumgeschraubt. Daher hätte man u.U. das Design dahingehend ändern könne, dass für jedes Kriterium eine Ja/Nein-Spalte existiert. Hätte die Abfrage enorm vereinfacht.

      meine Frage: Hat jemand eine Idee, wie man es besser lösen könnte?
      Mir ist das DB-Layout nicht genügend bekannt, die Inhalte auch nur bedingt, und leider vergaßt Du zu erwähnen, wie Dein Wunsch-Resultset aussieht. Mit diesen Informationen könnte sicherlich jemand noch spezifischer antworten.

      Betriebsblind :-(
      Wie gesagt, das Layout drum herum spielt eigentlich keine Rolle, zumal die Tabelle halt auch nur diese beiden Spalten hat.
      Es soll in einem Formular per Checkbox ausgewählt werden, was alles gesucht ist (quasi als Mindestanforderung). Ausgespuckt werden soll eine Liste mit Nutzern, die diese Kriterien (siehe oben: refcode) erfüllen. Und das soll eben notfalls auch für alle 83 Kriterien funktionieren und nicht nur für 50.

      Sorry für die reichlich mißverständliche Formulierung meinerseits, falls Du noch eine Idee auf Lager hast...

      Danke schonmal

      Thomas

      1. Hi,

        Welche Nutzer erfüllen Kriterium 1,10,60,61,62,...?

        SELECT questanscode, COUNT(*) FROM Activity_domains WHERE refcode IN (1,10,60,61,62) GROUP BY questanscode HAVING COUNT(*) = 5

        Letzteres Feld ist mit einer Tabelle verknüpft, die die Nutzerdaten enthält.

        Wie Du die Daten dazu parallel holst, weißt Du hoffentlich :-)

        In den nächsten Jahren wird sehr sicher an den Kriterien nicht rumgeschraubt. Daher hätte man u.U. das Design dahingehend ändern könne, dass für jedes Kriterium eine Ja/Nein-Spalte existiert. Hätte die Abfrage enorm vereinfacht.

        Die Zahl der Kriterien ist dennoch nicht als fix anzusehen - "vermutlich ändert sich nichts" ist kein Argument. Eine plötzliche wissenschaftliche Erkenntnis, eine neue Meinungsforschung, und schon hast Du auf einmal 117 Kriterien. Das DB-Layout für soetwas anzufassen ist Unsinn. Zudem vermindert es die Möglichkeiten generischer Scripts :-)

        Mir ist das DB-Layout nicht genügend bekannt, [...]
        Betriebsblind :-(

        Bekanntes Problem. Kannst Du mit obigem Statement was anfangen?

        Cheatah

        1. Hi,

          Welche Nutzer erfüllen Kriterium 1,10,60,61,62,...?
          SELECT questanscode, COUNT(*) FROM Activity_domains WHERE refcode IN (1,10,60,61,62) GROUP BY questanscode HAVING COUNT(*) = 5

          . . . D a n k e . . . !

          Nicht nur das es eine schlanke Lösung ist, nein, es hat mir grad noch ein anderes (aber hierfür uninteressantes Problem) aufgezeigt. Klasse!

          Letzteres Feld ist mit einer Tabelle verknüpft, die die Nutzerdaten enthält.
          Wie Du die Daten dazu parallel holst, weißt Du hoffentlich :-)

          Aber sicher doch :-) Oder wie sagte ein Freund neulich so nett zu mir: Nicht jeder, der sich nicht klar ausdrücken kann ist ein absoluter Anfänger... Ich belege also erstmal einen Kurs "Deutliches Problemschildern"

          In den nächsten Jahren wird sehr sicher an den Kriterien nicht rumgeschraubt. Daher hätte man u.U. das Design dahingehend ändern könne, dass für jedes Kriterium eine Ja/Nein-Spalte existiert. Hätte die Abfrage enorm vereinfacht.
          Die Zahl der Kriterien ist dennoch nicht als fix anzusehen - "vermutlich ändert sich nichts" ist kein Argument. Eine plötzliche wissenschaftliche Erkenntnis, eine neue Meinungsforschung, und schon hast Du auf einmal 117 Kriterien. Das DB-Layout für soetwas anzufassen ist Unsinn. Zudem vermindert es die Möglichkeiten generischer Scripts :-)

          Du hast ja eigentlich sowas von recht. Wenn man lange genug vor so einem Problem sitzt (was so eine schöne Lösung hat :) will man halt irgendwann doch einen Sprendsatz zünden, um die Fliege von der Wand zu holen.

          Mir ist das DB-Layout nicht genügend bekannt, [...]
          Betriebsblind :-(
          Bekanntes Problem. Kannst Du mit obigem Statement was anfangen?

          Danke, ja. Wurde bereits eingebaut und dient mir gleich mit zur Suche nach weiteren Fehlern.

          Beste Grüße & Danke nochmal

          Thomas

          1. Hi,

            Aber sicher doch :-) Oder wie sagte ein Freund neulich so nett zu
            mir: Nicht jeder, der sich nicht klar ausdrücken kann ist ein
            absoluter Anfänger... Ich belege also erstmal einen Kurs "Deutliches
            Problemschildern"

            Sonderlob für Problembewußtsein. ;-)

            Deine Belohnung hast Du ja bereits von Cheatah erhalten ...

            Viele Grüße
                  Michael

      2. Moin!

        Betriebsblind :-(
        Wie gesagt, das Layout drum herum spielt eigentlich keine Rolle, zumal die Tabelle halt auch nur diese beiden Spalten hat.
        Es soll in einem Formular per Checkbox ausgewählt werden, was alles gesucht ist (quasi als Mindestanforderung). Ausgespuckt werden soll eine Liste mit Nutzern, die diese Kriterien (siehe oben: refcode) erfüllen. Und das soll eben notfalls auch für alle 83 Kriterien funktionieren und nicht nur für 50.

        Ja, sag das doch gleich. Statt 50 Subselects nimm doch einfach sowas:

        SELECT * FROM kriteriumstabelle WHERE benutzerid = 'benutzer' AND (kriterium = '1' OR kriterium = '2' OR kriterium = '23'....)

        Du mußt im Prinzip nur alle gewünschten Kriterien, die abgefragt werden sollen, in die Klammer mit OR packen.

        Du erhälst für jedes vorhandene Kriterium eine Ergebniszeile. Damit kannst du ganz wunderbar eine Liste generieren. Außerdem geht es sicherlich wesentlich schneller.

        Was noch gut gehen kann (ich hab keine Ahnung, was das SQL von Access so kann), sind Mengenoperationen:

        SELECT ... WHERE benutzerid = 'benutzer' AND kriterium IN ('1','2','23',...)

        - Sven Rautenberg

        1. Hallo,

          Ja, sag das doch gleich. Statt 50 Subselects nimm doch einfach sowas:
          SELECT * FROM kriteriumstabelle WHERE benutzerid = 'benutzer' AND (kriterium = '1' OR kriterium = '2' OR kriterium = '23'....)
          Du mußt im Prinzip nur alle gewünschten Kriterien, die abgefragt werden sollen, in die Klammer mit OR packen.

          Hm...genaugenommen nein. Da ich ja Nutzer suche, kenne ich die NutzerID ja noch nicht. Und wenn ich ein Select * from tab where (kriterium = '1' OR kriterium = '2' OR ...) mache habe ich leider wieder (fast) alle - auch diejenigen, die eben nur die 1 erfüllen.

          Du erhälst für jedes vorhandene Kriterium eine Ergebniszeile. Damit kannst du ganz wunderbar eine Liste generieren. Außerdem geht es sicherlich wesentlich schneller.
          Was noch gut gehen kann (ich hab keine Ahnung, was das SQL von Access so kann), sind Mengenoperationen:
          SELECT ... WHERE benutzerid = 'benutzer' AND kriterium IN ('1','2','23',...)

          Jepp, sowas geht. Nur mit dem gleichen Problem wie oben.
          Cheatah hat eigentlich die optimale Lösung gehabt - anhand von COUNT. Damit sollte auch eine OR-Verknüpfung wieder laufen. Nur das ich auf _die_ Idee wirklich nicht gekommen wäre...

          Erstmal schönen Abend noch, viele Grüße & Danke

          Thomas

  2. Um jetzt einen Nutzer rauszusuchen, der viele Kriterien erfüllt,
    nutze ich bisher ein Konstrukt dieser Art

    Was sind denn "viele"?

    Ohne sicher zu sein, ob ich die Fragestellung richtig verstanden habe:
    SELECT id,COUNT(kriterium) as erfuellt_kriterien FROM tabelle GROUP BY id;

    1. Um jetzt einen Nutzer rauszusuchen, der viele Kriterien erfüllt,
      nutze ich bisher ein Konstrukt dieser Art
      Was sind denn "viele"?

      Es kann schon mal passieren, dass Nutzer mehr als 50 der 83 Kriterien erfüllen. Dementsprechend kann eine Suchanfrage auch mal auf mehr als 50 Kriterien hinauslaufen.

      Eine Präzisierung meines etwas unklaren Original-Beitrags ist in der Antwort auf Cheatahs Beitrag enthalten.

      Ohne sicher zu sein, ob ich die Fragestellung richtig verstanden habe:
      SELECT id,COUNT(kriterium) as erfuellt_kriterien FROM tabelle GROUP BY id;

      Leider knapp vorbei :-/ Die Anzahl brauch ich natürlich auch, das Problem ist das ermitteln derjenigen Nutzer, für die zu allen Kriterien ein Eintrag existiert.

      Falls dazu noch eine Idee vorhanden ist...ich stehe jeder Idee offen gegenüber.

      Viele Grüße

      Thomas