50

別のテーブルからの ID のリストを含めたい MySQL クエリがあります。Web サイトでは、ユーザーは特定のアイテムを追加でき、それらのアイテムをお気に入りに追加できます。私は基本的に、そのアイテムをお気に入りに登録した人の ID のリストを取得したいと考えています (これは少し単純化されていますが、要約すると次のようになります)。

基本的に、私は次のようなことをします:

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

このようにして、コード内で idlist を後で PHP の配列に分割することで、誰がアイテムをお気に入りにしたかを示すことができますが、次の MySQL エラーが発生します。

1242 - サブクエリが複数の行を返す

GROUP_CONCATそれが、たとえばCONCAT?の代わりに使用するポイントのようなものだと思いました。私はこれについて間違った方法で進んでいますか?


わかりました、これまでの回答に感謝します。うまくいくようです。ただし、落とし穴があります。そのユーザーによって追加されたアイテムもお気に入りと見なされます。そのため、作成者 = ユーザー ID かどうかを確認するために、追加のチェックが必要になります。誰かがこれを行うためのスマートな(そしてできれば効率的な)方法を考え出すのを手伝ってもらえますか?

ありがとうございました!

編集:私はこれをやろうとしました:

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

そしてidlistは空です。INNER JOIN代わりに使用するLEFT JOINと、空の結果が得られることに注意してください。ON要件を満たす行があると確信していますが。

4

5 に答える 5

121

OPはほとんどそれを正しくしました。完全なサブクエリGROUP_CONCATではなく、サブクエリで列をラップする必要があります(カンマがデフォルトであるため、セパレーターを却下しています):

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

これにより、目的の結果が得られますが、サブクエリで外部スコープ変数にアクセスできるため、受け入れられた回答が部分的に間違っていることも意味します。

于 2012-03-25T08:30:53.317 に答える
14

このようなクエリでは、外部スコープの変数にアクセスできません (items.idそこでは使用できません)。むしろ次のようなものを試してください

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;

必要に応じてフィールドのリストを展開します (名前、色...)。

于 2008-12-18T13:50:54.330 に答える
2

「userid = itemid」が間違っている可能性があると思いますが、次のようにすべきではありません。

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
于 2008-12-19T02:36:40.010 に答える
1

はい、soulmergeの解決策は大丈夫です。しかし、より多くの子テーブルからデータを収集する必要があるクエリが必要でした。次に例を示します。

  • メインテーブル:セッション(プレゼンテーションセッション) (uid, name, ..)
  • 1 番目の子テーブル:キー session_id を持つイベント(uid、session_uid、date、time_start、time_end)
  • 2 番目の子テーブル: accessories_needed (ラップトップ、プロジェクター、マイクなど) とキー session_id (uid、session_uid、accessory_name)
  • 3 番目の子テーブル:キー session_id (uid、session_uid、presenter_name、address...) を持つsession_presenters (発表者)

すべてのセッションは、子テーブルのテーブルにより多くの行を持ちます (より多くのタイム スケジュール、より多くの付属品)

また、すべてのセッションを 1 つのコレクションに集めて、鉱石の行 (一部) に表示する必要がありました。

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

私の解決策(何時間もの実験の後):

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

したがって、JOIN や GROUP BY は必要ありません。データをわかりやすく表示するためのもう 1 つの便利な機能 (「エコー」する場合):

  • events.date、time_start、time_end などを「<UL><LI> ... </LI></UL>」でラップして、「<LI></LI>」をクエリのセパレータとして使用することができます結果をリスト項目に分けます。

これが誰かに役立つことを願っています。乾杯!

于 2011-12-15T14:38:09.497 に答える