如何连接表而不重复多次列值?

时间:2013-04-26 18:36:53

标签: mysql sql join

我有3张桌子:图片,颜色和标签。 每个图像有2种颜色和至少1个标签。 我希望我的用户可以单独搜索标签或/和颜色。

问题是当我加入表格时,我会在列中多次获得具有相同值的行。

SELECT images.id, tag, color
FROM images
JOIN tags ON tags.image_id = images.id
JOIN colors ON colors.image_id = images.id
WHERE images.id = 1

I get:
image_id: 1, tag: sky, color: blue
image_id: 1, tag: cloud, color: blue
image_id: 1, tag: sky, color: white
image_id: 1, tag: cloud, color: white

But the result I want is something like:
image_id: 1, tag1: sky, tag2: cloud, color1: blue, color2: white

这有可能吗?或者我应该改变数据库设计?

1 个答案:

答案 0 :(得分:1)

函数group_concat()将把所有标记或颜色值放到一个字段中,不管你喜欢什么样的分隔符:

SELECT images.id, group_concat(distinct tag separator ', ') as tags,
       group_concat(distinct color separator ', ') as colors
FROM images
left JOIN tags ON tags.image_id = images.id
left JOIN colors ON colors.image_id = images.id
WHERE images.id = 1
group by images.id

(在这种情况下,严格来说group by不是必需的,因为您要过滤到一个组。但是您可能想要消除where子句并查看多个ID。)< / p>

distinct关键字可以防止重复,这很重要,因为您的查询会在标记和颜色之间生成笛卡尔积。如果您有4个标签和3种颜色,则查询会为每个ID生成4 * 3 = 12行。我确实将连接更改为左外连接,因此您将看到缺少标签或缺少颜色的ID。

您实际上请求1tag1 , tag2 , color1 , and color2`作为输出。好吧,如果最多有两个值,那么你很幸运:

SELECT images.id,
       min(tag) as tag1, max(tag) as tag2,
       min(color) as color1, max(color) as color2
FROM images
left JOIN tags ON tags.image_id = images.id
left JOIN colors ON colors.image_id = images.id
WHERE images.id = 1
group by images.id

使用更多颜色或标签时,您会遇到问题。 SQL查询具有固定数量的列 - 也就是说,您不能仅因为在ID上添加新颜色而添加另一列。此外,在MySQL中,很难枚举(可能,但不是标准SQL)。如果您有两种以上的颜色或标签,请使用group_concat()