如何在join字段中使用逗号分隔列表连接两个表

Kat*_*tie 12 mysql csv join

我有两张桌子,categoriesmovies.

movies表格中我有一个专栏categories.该列包含电影适合的类别.类别是以逗号分隔的ID.

这是一个例子:

Table categories {
  -id-       -name-
  1          Action
  2          Comedy
  4          Drama
  5          Dance
}

Table movies {
  -id-       -categories-  (and some more columns ofc)
  1          2,4
  2          1,4
  4          3,5
}
Run Code Online (Sandbox Code Playgroud)

现在回答实际问题:是否可以执行从电影表中排除类别列的查询,而是从类别表中选择匹配的类别并将它们返回到数组中?就像一个连接,但问题是有多个用逗号分隔的类别,是否有可能做某种正则表达式?

Kar*_*lis 18

select
    m.id,
    group_concat(c.name)
from
    movies m
    join categories c on find_in_set(c.id, m.categories)
group by
    m.id
Run Code Online (Sandbox Code Playgroud)

输出应该是这样的:

Table movies {
  -id-       -categories-
  1          Comedy,Drama
  2          Action,Drama
  4          Other,Dance
}
Run Code Online (Sandbox Code Playgroud)


Joh*_*ica 12

在数据库字段中使用逗号分隔列表是一种反模式,应该不惜一切代价避免使用.
因为它是一个PITA,用于在SQL中提取那些以逗号分隔的值.

相反,您应该添加一个单独的链接表来表示类别和电影之间的关系,如下所示:

Table categories
  id integer auto_increment primary key
  name varchar(255)

Table movies
  id integer auto_increment primary key
  name varchar(255)

Table movie_cat
  movie_id integer foreign key references movies.id
  cat_id integer foreign key references categories.id
  primary key (movie_id, cat_id)
Run Code Online (Sandbox Code Playgroud)

现在你可以做到

SELECT m.name as movie_title, GROUP_CONCAT(c.name) AS categories FROM movies m
INNER JOIN movie_cat mc ON (mc.movie_id = m.id)
INNER JOIN categories c ON (c.id = mc.cat_id)
GROUP BY m.id
Run Code Online (Sandbox Code Playgroud)

回到你的问题
交替使用你可以做的数据

SELECT m.name as movie_title
  , CONCAT(c1.name, if(c2.name IS NULL,'',', '), ifnull(c2.name,'')) as categories 
FROM movies m
LEFT JOIN categories c2 ON 
 (replace(substring(substring_index(m.categories, ',', 2),
  length(substring_index(m.categories, ',', 2 - 1)) + 1), ',', '') = c2.id)
INNER JOIN categories c1 ON 
 (replace(substring(substring_index(m.categories, ',', 1), 
  length(substring_index(m.categories, ',', 1 - 1)) + 1), ',', '') = c1.id)
Run Code Online (Sandbox Code Playgroud)

请注意,最后一个查询仅在每部电影有2个或更少类别时才有效.

  • @Johan:这并不意味着您必须为其创建一个无意义且任意的自动递增整数字段。将主键放在 `(movie_id,cat_id)` 上大声喊叫!这个 `movie_cat`.`id` 是 100% 毫无意义的。 (2认同)