Frage

Ich habe eine MySQL-Abfrage, in die ich eine Liste von IDs aus einer anderen Tabelle einschließen möchte.Auf der Website können Benutzer bestimmte Artikel hinzufügen und diese Artikel dann zu ihren Favoriten hinzufügen.Grundsätzlich möchte ich die Liste der IDs der Personen erhalten, die diesen Artikel als Favorit markiert haben (das ist etwas vereinfacht, aber das ist es, worauf es hinausläuft).

Im Grunde mache ich so etwas:

SELECT *,
GROUP_CONCAT((SELECT userid FROM favourites WHERE itemid = items.id) SEPARATOR ',') AS idlist
FROM items
WHERE id = $someid

Auf diese Weise könnte ich zeigen, wer ein Element favorisiert hat, indem ich die Idlist später in einem PHP-Array weiter unten in meinem Code aufteile. Ich erhalte jedoch den folgenden MySQL-Fehler:

1242 – Unterabfrage gibt mehr als eine Zeile zurück

Ich dachte, das wäre irgendwie der Sinn der Verwendung GROUP_CONCAT statt beispielsweise CONCAT?Mache ich das falsch?


Ok, danke für die bisherigen Antworten, das scheint zu funktionieren.Allerdings gibt es einen Haken.Elemente gelten auch dann als Favorit, wenn sie von diesem Benutzer hinzugefügt wurden.Daher bräuchte ich eine zusätzliche Prüfung, um zu prüfen, ob Ersteller = Benutzer-ID.Kann mir jemand helfen, eine intelligente (und hoffentlich effiziente) Möglichkeit zu finden, dies zu tun?

Danke schön!

Bearbeiten:Ich habe gerade versucht, Folgendes zu tun:

SELECT [...] LEFT JOIN favourites ON (userid = itemid OR creator = userid)

Und Id-Liste ist leer.Beachten Sie, dass, wenn ich verwende INNER JOIN anstatt LEFT JOIN Ich erhalte ein leeres Ergebnis.Auch wenn ich mir sicher bin, dass es Zeilen gibt, die die ON-Anforderung erfüllen.

War es hilfreich?

Lösung

Sie keine Variablen in dem äußeren Umfang in solchen Abfragen zugreifen können (kann dort nicht verwenden items.id). Sie sollten vielmehr versuchen, so etwas wie

SELECT
    items.name,
    items.color,
    CONCAT(favourites.userid) as idlist
FROM
    items
INNER JOIN favourites ON items.id = favourites.itemid
WHERE
    items.id = $someid
GROUP BY
    items.name,
    items.color;

Erweitern Sie die Liste der Felder nach Bedarf (Name, Farbe ...).

Andere Tipps

OP bekam fast es richtig. GROUP_CONCAT soll die Spalten in der Unterabfrage wurde Verpackung und nicht die komplette Unterabfrage (Ich entlassen den Separator weil Komma ist die Standardeinstellung ):

SELECT i.*,
(SELECT GROUP_CONCAT(userid) FROM favourites f WHERE f.itemid = i.id) AS idlist
FROM items i
WHERE i.id = $someid

Dies wird das gewünschte Ergebnis liefern und bedeutet auch, dass die akzeptierte Antwort teilweise falsch ist, weil Sie äußere Umfang Variablen in einer Unterabfrage zugreifen können.

Ich glaube, Sie haben „userid = itemid“ falsch, es sollte nicht so sein:

SELECT ITEMS.id,GROUP_CONCAT(FAVOURITES.UserId) AS IdList
FROM FAVOURITES 
INNER JOIN ITEMS ON (ITEMS.Id = FAVOURITES.ItemId OR FAVOURITES.UserId = ITEMS.Creator)
WHERE ITEMS.Id = $someid
GROUP BY ITEMS.ID

Der Zweck GROUP_CONCAT ist richtig, aber die Unterabfrage ist nicht erforderlich, und das Problem verursacht. Versuchen Sie stattdessen:

SELECT ITEMS.id,GROUP_CONCAT(FAVOURITES.UserId)
FROM FAVOURITES INNER JOIN ITEMS ON ITEMS.Id = FAVOURITES.ItemId
WHERE ITEMS.Id = $someid
GROUP BY ITEMS.ID

Ja, die Lösung von Soulmerge ist in Ordnung.Aber ich brauchte eine Abfrage, bei der ich Daten aus weiteren untergeordneten Tabellen sammeln musste, zum Beispiel:

  • Haupttabelle: Sitzungen (Präsentationssitzungen) (UID, Name, ..)
  • 1. Kindertisch: Veranstaltungen mit Schlüssel session_id (uid, session_uid, date, time_start, time_end)
  • 2. Kindertisch: accessoires_needed (Laptop, Projektor, Mikrofone usw.) mit Schlüssel session_id (uid, session_uid, accessoire_name)
  • 3. Kindertisch: session_presenters (Vortragende Personen) mit Schlüssel session_id (uid, session_uid, vortragender_Name, Adresse...)

Jede Sitzung hat mehr Zeilen in untergeordneten Tabellen (mehr Zeitpläne, mehr Zubehör).

Und ich musste für jede Sitzung eine Sammlung sammeln, um sie in der Erzzeile anzuzeigen (einige davon):

session_id | session_name | date | time_start | time_end | accessories | presenters

Meine Lösung (nach vielen Stunden des Experimentierens):

SELECT sessions.uid, sessions.name,
    ,(SELECT GROUP_CONCAT( `events`.date SEPARATOR '</li><li>') 
            FROM `events` 
            WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS date
    ,(SELECT GROUP_CONCAT( `events`.time_start SEPARATOR '</li><li>') 
            FROM `events` 
            WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS time_start
    ,(SELECT GROUP_CONCAT( `events`.time_end SEPARATOR '</li><li>') 
            FROM `events` 
            WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS time_end
    ,(SELECT GROUP_CONCAT( accessories.name SEPARATOR '</li><li>') 
            FROM accessories 
            WHERE accessories.session_id = sessions.uid ORDER BY accessories.name) AS accessories
    ,(SELECT GROUP_CONCAT( presenters.name SEPARATOR '</li><li>') 
            FROM presenters
            WHERE presenters.session_id = sessions.uid ORDER BY presenters.name) AS presenters

    FROM sessions

Es ist also kein JOIN oder GROUP BY erforderlich.Eine weitere nützliche Sache, um Daten benutzerfreundlich anzuzeigen (beim „Echo“):

  • Sie können events.date, time_start, time_end usw. in „<UL><LI> ...“ einschließen.</LI></UL>“, sodass das in der Abfrage als Trennzeichen verwendete „<LI></LI>“ die Ergebnisse in Listenelemente trennt.

Ich hoffe, das hilft jemandem.Prost!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top