LEFT表(简化)是:
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)以使其工作,但我想避免这种情况。
答案 0 :(得分: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”)和一个包含其关系的表。这将确保,例如,鲍勃决定通过“罗伯特”,你不必去除整个标签表,但只有涉及鲍勃的一行。
<强>更新强>
所以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 |
+------+-----------------------------+
答案 1 :(得分: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;