0

左の表 (簡略化) は次のとおりです。

id
name (ex:Bob)
tags (ex:1,4,6)

右の表は次のとおりです。

id
tag (ex:Sailing)

次のような LEFT テーブルの結果を取得したい:

row 1:
   name: Bob
   tags: Sailing,Snowboard,...

私が得た最も近いものはそこにありました:

SELECT `name`, GROUP_CONCAT(`right`.`tag`) AS tags
FROM (`left`)
LEFT OUTER JOIN `right` ON `right`.`id` IN(left.tags)
ORDER BY `name` asc

しかし、これは GROUP_CONCAT() のために 1 行しか与えません。それがなければ、すべての結果が表示されますが、コンマ区切りリストの最初のタグのみが表示されます。私は近くにいることを知っていますが、これで多くの時間を失っています。どんな助けでも感謝します。

行(id、left_id、right_id)を含む3番目のテーブルleft_rightを作成して機能させることができることはわかっていますが、それは避けたいと思います。

4

2 に答える 2

1

名前フィールドに GROUP BY を追加してみてください。タグ付きのすべての名前のリストを選択できるはずです。

SELECT `name`, GROUP_CONCAT(`right`.`tag`) AS tags
FROM (`left`)
LEFT OUTER JOIN `right` ON `right`.`id` IN(left.tags)
GROUP BY `name`
ORDER BY `name` ASC;
于 2012-09-20T18:45:46.717 に答える
1

まず第一に、bažmegakapa が言ったことは正しいです。あなたが説明したセットアップを正しく理解していれば、すでにかなりのスペース (およびパフォーマンス) を無駄にしています。

あなたはこれを行うことができます:

CREATE TABLE pleft ( id integer, name varchar(20), tags integer );
CREATE TABLE pright ( id integer, tag varchar(20));

INSERT INTO pleft VALUES ( 1, 'Bob', 1 ), ( 9, 'Bob', 4 ), ( 15, 'Bob', 6 );
INSERT INTO pleft VALUES ( 2, 'Ann', 1 ), ( 3, 'Joe', 4 ), ( 4, 'Joe', 6 );

INSERT INTO pright VALUES ( 1, 'Sailing' ), ( 4, 'Snowboarding' ), ( 6, 'Skiing' );


SELECT pleft.name, GROUP_CONCAT(pright.tag)
    FROM pleft JOIN pright ON ( pleft.tags = pright.id )
    GROUP BY pleft.name ORDER BY pleft.name;

+------+-----------------------------+
| name | GROUP_CONCAT(pright.tag)    |
+------+-----------------------------+
| Ann  | Sailing                     |
| Bob  | Sailing,Skiing,Snowboarding |
| Joe  | Snowboarding,Skiing         |
+------+-----------------------------+

pleft...しかし、テーブルの各行で名前が不必要に重複していることに注意してください。理想的には、人物をモデル化する 1 つのテーブル (id=1, name="Bob")、タグをモデル化する 1 つのテーブル (id=6, value="Skiing")、およびそれらの関係を含む 1 つのテーブルが必要です。これにより、たとえば、ボブが「ロバート」を使用することを決定した場合、タグ テーブル全体を de-bob する必要はなく、ボブに関連する 1 行だけを削除する必要があります。

アップデート

「 1,4,6 tags」を保持する varchar フィールドも同様です。同じロジックが適用されますが、再度結合する前にフィールドを分割する必要があります。"11" は true を返すため、"1 in tags" のようなものは使用できません ("1" は "11" に含まれます)。(これは、"Jaywalking" として知られる SQL アンチパターンです: https://groups.google.com/forum/?fromgroups=#!topic/django-users/5j4AmQE6nTkなどを参照してください)

SELECT pleft.name, GROUP_CONCAT(pright.tag)
FROM pleft JOIN pright
    ON ( CONCAT(',',pleft.tags,',') LIKE CONCAT('%,',pright.id,',%' ))
GROUP BY pleft.name ORDER BY pleft.name;

もう 1 つの方法は、ストアド プロシージャを使用することです。 http://www.marcogoncalves.com/2011/03/mysql-split-column-string-into-rows/を参照してください。

CREATE TABLE pleft ( id integer, name varchar(20), tags varchar(20) );
INSERT INTO pleft VALUES ( 1, 'Bob', '1,4,6' ), ( 2, 'Jill', '4,1' );
SELECT pleft.name, GROUP_CONCAT(pright.tag)
    FROM pleft JOIN pright
        ON ( CONCAT(',',pleft.tags,',') LIKE CONCAT('%,',pright.id,',%' ))
    GROUP BY pleft.name ORDER BY pleft.name;
+------+-----------------------------+
| name | GROUP_CONCAT(pright.tag)    |
+------+-----------------------------+
| Bob  | Sailing,Snowboarding,Skiing |
| Jill | Sailing,Snowboarding        |
+------+-----------------------------+
于 2012-09-20T18:41:30.237 に答える