如何添加';和';mysql中的标记排除

如何添加';和';mysql中的标记排除,mysql,Mysql,我需要创建电影标题的过滤浏览。用户可以搜索所有包含浪漫、戏剧类型/标签的电影,但不得包含喜剧 CREATE TABLE `movies` ( `id` int NOT NULL AUTO_INCREMENT, `title` varchar(100) NOT NULL DEFAULT '', PRIMARY KEY(`id`) ); CREATE TABLE `genres` ( `id` int NOT NULL AUTO_INCREMENT, `gname` var

我需要创建电影标题的过滤浏览。用户可以搜索所有包含浪漫、戏剧类型/标签的电影,但不得包含喜剧

CREATE TABLE `movies` (
  `id` int NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL DEFAULT '',
 
  PRIMARY KEY(`id`)
);

CREATE TABLE `genres` (
  `id` int NOT NULL AUTO_INCREMENT,
  `gname` varchar(32) NOT NULL DEFAULT '',
  PRIMARY KEY(`id`)
);

CREATE TABLE `genres_in_movies` (
  `genre_id` int NOT NULL,
  `movie_id` int NOT NULL,
  FOREIGN KEY (`genre_id`) REFERENCES `genres`(`id`),
  FOREIGN KEY (`movie_id`) REFERENCES `movies`(`id`)
);

INSERT INTO genres(gname) VALUES('Comedy'),('Horror'),('Drama'),('Suspense'),('Romance'),('Documentary');

INSERT INTO movies(title) VALUES("Zoolander"),("Inception"),("Jurassic");

insert into genres_in_movies(genre_id,movie_id) values 
(1,1),(3,1),(5,1),
(2,2),(4,2),
(6,2),
(1,3),(2,3),(3,3);
我在下面所做的使包含部分工作正常

SELECT DISTINCT m.id, m.title, gim.genres
FROM movies m
INNER JOIN genres_in_movies ON movie_id = m.id
INNER JOIN (
  SELECT movie_id, group_concat(genres.gname) as genres
  FROM genres_in_movies
  INNER JOIN genres ON genre_id = genres.id
  GROUP by movie_id
) AS gim ON gim.movie_id = m.id
WHERE genres_in_movies.genre_id IN (5)
AND genres_in_movies.genre_id not in(1)
但是,包含通过使用OR起作用,如果我只是为排除添加一个NOT IN子句,它将不起作用,因为排除需要使用and

我找到的唯一解决方案是在mssql中使用临时表和复制数据,这可能非常慢。我在这里找到了很多解决方案,但没有一个能满足我的需要


fiddle有我的数据库结构和当前进度。

正在添加一个简单的
,不存在
,子查询可以帮助您吗

SELECT DISTINCT m.id, m.title, gim.genres
FROM movies m
INNER JOIN genres_in_movies AS inclusionGenres ON inclusionGenres.movie_id = m.id
INNER JOIN (
  SELECT movie_id, group_concat(genres.gname) as genres
  FROM genres_in_movies
  INNER JOIN genres ON genre_id = genres.id
  GROUP by movie_id
) AS gim ON gim.movie_id = m.id
WHERE inclusionGenres.genre_id IN (5)
AND NOT EXISTS(SELECT 1 FROM genres_in_movies AS exlusionGenres WHERE exlusionGenres.movie_id = m.id AND exlusionGenres.genre_id in(1))
我认为加入“排除类型”也是可能的

编辑、添加连接示例:

SELECT DISTINCT m.id, m.title, gim.genres
FROM movies m
INNER JOIN genres_in_movies AS inclusionGenres ON inclusionGenres.movie_id = m.id
INNER JOIN (
  SELECT movie_id, group_concat(genres.gname) as genres
  FROM genres_in_movies
  INNER JOIN genres ON genre_id = genres.id
  GROUP by movie_id
) AS gim ON gim.movie_id = m.id
LEFT JOIN genres_in_movies AS exlusionGenres ON (exlusionGenres.movie_id = m.id AND exlusionGenres.genre_id in(3))
WHERE inclusionGenres.genre_id IN (5)
AND exlusionGenres.genre_id IS NULL;

使用子查询添加简单的
而不存在的
是否有帮助

SELECT DISTINCT m.id, m.title, gim.genres
FROM movies m
INNER JOIN genres_in_movies AS inclusionGenres ON inclusionGenres.movie_id = m.id
INNER JOIN (
  SELECT movie_id, group_concat(genres.gname) as genres
  FROM genres_in_movies
  INNER JOIN genres ON genre_id = genres.id
  GROUP by movie_id
) AS gim ON gim.movie_id = m.id
WHERE inclusionGenres.genre_id IN (5)
AND NOT EXISTS(SELECT 1 FROM genres_in_movies AS exlusionGenres WHERE exlusionGenres.movie_id = m.id AND exlusionGenres.genre_id in(1))
我认为加入“排除类型”也是可能的

编辑、添加连接示例:

SELECT DISTINCT m.id, m.title, gim.genres
FROM movies m
INNER JOIN genres_in_movies AS inclusionGenres ON inclusionGenres.movie_id = m.id
INNER JOIN (
  SELECT movie_id, group_concat(genres.gname) as genres
  FROM genres_in_movies
  INNER JOIN genres ON genre_id = genres.id
  GROUP by movie_id
) AS gim ON gim.movie_id = m.id
LEFT JOIN genres_in_movies AS exlusionGenres ON (exlusionGenres.movie_id = m.id AND exlusionGenres.genre_id in(3))
WHERE inclusionGenres.genre_id IN (5)
AND exlusionGenres.genre_id IS NULL;
以下是我的看法:

SELECT movie_id, title, group_concat(genres.gname) as genres
  FROM genres_in_movies
  INNER JOIN genres ON genre_id = genres.id
  INNER JOIN movies ON genres_in_movies.movie_id=movies.id
  GROUP by movie_id
  HAVING FIND_IN_SET('Romance',genres) 
    AND NOT FIND_IN_SET('Comedy',genres);
由于您使用的是
GROUP\u CONCAT
,因此可以在末尾添加一个带有
HAVING
子句的函数。

以下是我的观点:

SELECT movie_id, title, group_concat(genres.gname) as genres
  FROM genres_in_movies
  INNER JOIN genres ON genre_id = genres.id
  INNER JOIN movies ON genres_in_movies.movie_id=movies.id
  GROUP by movie_id
  HAVING FIND_IN_SET('Romance',genres) 
    AND NOT FIND_IN_SET('Comedy',genres);

因为您使用的是
GROUP\u CONCAT
,所以可以在末尾添加一个带有
HAVING
子句的函数。

非常有趣地使用了
SUM()
!以前从未读过这样的用法。我对此投赞成票。
SUM()
的用法非常有趣!以前从未读过这样的用法。我对此投赞成票。我认为使用拉丁字母是错误的。为什么?我需要一个可以支持日语/汉语的字符集。那么Latin1将如何帮助您呢?不是,我应该使用哪一个?UTF?是的,UTF8(mb4)。我认为使用拉丁字符是错误的。为什么?我需要一个可以支持日语/汉语的字符集。那么Latin1将如何帮助您呢?不是,我应该使用哪一个?UTF?是的,UTF8(mb4).Hm,这不适用于多个标签。我只是用了“喜剧,戏剧”,但没有找到结果。这是因为组_concat而比较字符串吗?不幸的是
FIND_IN_SET
仅查找由逗号(,)分隔的子字符串。。要从结果中省略“喜剧”和“戏剧”,您需要在
未在集合中查找(“戏剧”,流派)
之后添加另一个
和未在集合中查找(“喜剧”,流派)
。嗯,这不适用于多个标记。我只是用了“喜剧,戏剧”,但没有找到结果。这是因为组_concat而比较字符串吗?不幸的是
FIND_IN_SET
仅查找由逗号(,)分隔的子字符串。。要从结果中省略“喜剧”和“戏剧”,您需要在
未在集合中查找(“戏剧”,流派)
之后添加另一个
和未在集合中查找(“喜剧”,流派)