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(),这给了我一行。没有它,它会给我所有的结果,但只有逗号分隔列表中的第一个标签。我知道我已经很接近了,但我在这方面浪费了太多时间。任何帮助表示赞赏。

我知道我可以创建第三个表 left_right,其中包含行(id、left_id、right_id)以使其工作,但我想避免这种情况。

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表格的每一行中是如何不必要地重复的。理想情况下,您将有一张表对人进行建模:(id=1, name="Bob"),一张表对标签进行建模 (id=6, value="Skiing") 和一张包含它们的关系的表。这将确保,例如,Bob 决定使用“Robert”,您不必对整个标签表进行 de-bob,而只需对涉及 Bob 的一行进行 de-bob。

更新

tags持有“1,4,6”的 varchar 字段也是如此。同样的逻辑也适用,但现在我们必须在重新组合之前拆分字段。你不能使用像“1 in tags”这样的东西,因为“11”会返回true(“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;

另一种方法是使用存储过程:请参阅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 回答