Helmuth: Schnittmenge mehrerer Abfragen (oder alles in einer Abfrage?)

Hallo,

ich hab eine (fertige, fremde) Datenbank übernommen - kann am Design also nichts grundlegendes mehr ändern. Es geht darum mehrere Einträge nach mehreren Kriterien abzufragen, zu sortieren und die Qualität des Treffers zu ermitteln.

Die DB schaut folgendermaßen aus:

mood    | cd_id | ranking

traurig | 1     | 1
traurig | 12    | 2
traurig | 3     | 3
jazz    | 4     | 1
langsam | 1     | 3
langsam | 4     | 2
langsam | 12    | 3

Bei der Abfrage kann man die einzelnen Kriterien auch werten, also zb.

Traurig 3, Langsam 1

Wie müsste nun die entsprechende Abfrage ausschauen damit ich alle Treffer bekomm in der Reihenfolge: Alle Kriterien erfüllt (nach ranking sortiert) und dann halt absteigend, 3,2,1 Kriterium erfüllt je nach Anzahl der Kriterien.

Im Beispiel:
cd_id 12 (traurig und langsam)
cd_id 1 (auch traurig und langsam, schlechteres ranking)
cd_id 3 (nur traurig, aber dafür sehr)
cd_id 4 (langsam)

Bin nicht so der Datenbank-Held, vielleicht kann mir hier jemand auf die Sprünge helfen...

Danke,

Helmuth

  1. Bin nicht so der Datenbank-Held, vielleicht kann mir hier jemand auf die Sprünge helfen...

    Irgendwas probiert? Bspw. ein SELECT, einen JOIN, ein GROUP, ein SUM(), ein ORDER BY? Irgendwelche SQL-Kenntnisse? Wie heisst die DB?

    1. Bin nicht so der Datenbank-Held, vielleicht kann mir hier jemand auf die Sprünge helfen...

      Irgendwas probiert? Bspw. ein SELECT, einen JOIN, ein GROUP, ein SUM(), ein ORDER BY? Irgendwelche SQL-Kenntnisse? Wie heisst die DB?

      Nun, meine SQL-Kenntnisse reichen für grundlegende Datenbank-Anwendungen. Hier fehlt mir der Ansatz wie die Abfrage ausschauen muss, damit ich alle Datensätze erhalte die alle Bedingungen erfüllen. Ich will nicht, dass hier jemand die Abfrage für mich programmiert, ich weiß nur nicht wonach ich suchen soll.

      Müsste ich die Anfrage beschreiben, wäre das

      Liefer mir alle CDs bei denen in der Spalte mood 'traurig' und 'langsam' vorkommt und sortiere sie nach ranking.

      Damit hätte ich die 100% Treffer und könnte in einer weiteren Abfrage

      Liefer mir alle CDs bei denen in der Spalte mood 'traurig' ODER 'langsam' vorkommt und sortieren nach ranking.

      alle 50% Treffer abfragen. Fehlt nur die Übersetzung in mysql...

      Ein "SELECT cd_id FROM mood_cd WHERE mood = 'traurig' AND mood = 'langsam'" funktioniert leider nicht.

      IN ('traurig', 'langsam') liefert sowohl traurig als auch langsam, aber keine Schnittmenge.

      Danke für die Hilfe!

      1. n'abend,

        schön zu wissen wäre welches DBMS du denn benutzen willst. Mysql? PostgreSQL? [...] welche Version?

        Das ist in soweit relevant, als dass manche Funktionen erst ab gewissen Versionen zur Verfügung stehen. MySQL kann bspw. SubSelects erst ab 4.1.

        Wie und ob man dein Problem in einer Query (mit ggf. SubSelects und oder verwirrenden JOINS) lösen kann, weiss ich nicht. Ich bin allerdings auch kein Fan von hyperkomplexen SQL-Queries; zumindest nicht in Sachen MySQL.

        IN ('traurig', 'langsam') liefert sowohl traurig als auch langsam, aber keine Schnittmenge.

        Du könntest durchaus deine Abfrage auf diese Weise machen.
        SELECT cd_id, mood, ranking FROM tablename WHERE mood IN ('traurig', 'langsam') ORDER BY ranking;
        Dann bekommst du alle Datensätze, die den gewählten moods entsprechen, nach ranking sortiert. CDs, die mehrere der gewünschten moods entsprechen, werden dabei entsprechend oft in der Ergebnismenge vorkommen.

        Würdes du obige Abfrage auf deine Demodaten loslassen, würdest du also etwa das folgende erhalten:

        cd_id   | mood          | ranking
        --------+---------------+---------
        1       | traurig       | 1
        --------+---------------+---------
        12      | traurig       | 2
        --------+---------------+---------
        4       | langsam       | 2
        --------+---------------+---------
        3       | traurig       | 3
        --------+---------------+---------
        1       | langsam       | 3
        --------+---------------+---------
        12      | langsam       | 3

        mit geschicktem Sortieren (im Dinne von gruppieren) der Daten, solltest du dein Ziel erreichen. Wenn du Probleme mit dem Finden einer geeigneten Struktur zur Analyse und Zwischenspeicherung deiner Daten hast, kannst du gerne wieder nachfragen.

        Anmerkung:
        'langsam' ist für mich übrigens kein "mood", sondern eher "pace" oder "tempo".

        weiterhin schönen abend...

        --
        Freundlich wie man war, hat man mir Großbuchstaben geschenkt.
        sh:( fo:# ch:# rl:° br:> n4:& ie:{ mo:} va:) de:] zu:} fl:{ ss:? ls:[ js:|
      2. Hallo

        Müsste ich die Anfrage beschreiben, wäre das

        Liefer mir alle CDs bei denen in der Spalte mood 'traurig' und 'langsam' vorkommt und sortiere sie nach ranking.

        Pro Datensatz können in einer Spalte (in einem normalisierten Datenmodell) nicht zwei verschiedene Werte drin stehen, wenn sich nicht in Fliesstextform den Spalteninhalt bilden.

        Deswegen kann

        Ein "SELECT cd_id FROM mood_cd WHERE mood = 'traurig' AND mood = 'langsam'" funktioniert leider nicht.

        auch nicht funktionieren.

        Ein IN (wert, wert, wert, ...) war schon gar nicht so schlecht, du musst danach nur noch nach der CD-Nummer (oder was für eine Identifikation du dafür hast) gruppieren und für die diese Gruppierung mit Count() die Datensätze zählen und dann auch nach Count() sortieren.

        HTH,
        Frank