You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现SQL查询:返回同时包含所有指定流派的动漫记录

解决同时匹配多个流派的SQL查询问题

这个需求很典型——从存储多流派的字段里筛选出同时包含所有目标流派的记录,而不是只要有一个就返回。我根据不同的字段存储格式和数据库类型,给你几种实用的解决方案:

场景1:genre是逗号分隔的字符串(比如"Action,Comedy,Romance")

这种情况要注意精确匹配,不能直接用LIKE '%Action%',否则会误匹配类似"Action-adventure"的流派。

方案1:用数据库内置的多值判断函数

  • MySQL/MariaDB:用FIND_IN_SET,它会精准匹配逗号分隔列表中的值:
SELECT *
FROM anime
WHERE FIND_IN_SET('Action', genre) > 0
  AND FIND_IN_SET('Comedy', genre) > 0
  AND FIND_IN_SET('Romance', genre) > 0;

FIND_IN_SET返回目标值在列表中的位置,大于0就表示存在,三个条件同时满足就说明记录包含所有三个流派。

  • PostgreSQL:把字符串转成数组后用包含操作符@>:
SELECT *
FROM anime
WHERE STRING_TO_ARRAY(genre, ',') @> ARRAY['Action', 'Comedy', 'Romance'];

@>表示左边的数组完全包含右边的所有元素,正好符合你的需求。

方案2:用正则表达式精准匹配

如果你的数据库支持正则,可以用正则来匹配每个流派的独立存在:

-- MySQL示例
SELECT *
FROM anime
WHERE genre REGEXP '(^|,)Action(,|$)'
  AND genre REGEXP '(^|,)Comedy(,|$)'
  AND genre REGEXP '(^|,)Romance(,|$)';

(^|,)匹配字符串开头或逗号,(,|$)匹配逗号或字符串结尾,确保不会匹配到部分包含的流派名称。

场景2:genre是数组类型(比如PostgreSQL的text[]、MySQL的JSON数组)

这种原生多值类型的查询会更简单:

  • PostgreSQL数组:直接用@>操作符:
SELECT *
FROM anime
WHERE genre @> ARRAY['Action', 'Comedy', 'Romance'];
  • MySQL JSON数组:多次使用JSON_CONTAINS判断每个流派是否存在:
SELECT *
FROM anime
WHERE JSON_CONTAINS(genre, '"Action"')
  AND JSON_CONTAINS(genre, '"Comedy"')
  AND JSON_CONTAINS(genre, '"Romance"');

注意这里要给流派名称加双引号,因为JSON字符串必须用双引号包裹。

通用方案:拆分多值字段后分组统计

如果上面的方法不适用,你可以先把多值字段拆分成单独的行,再通过分组统计来筛选:

-- MySQL示例,用递归CTE拆分逗号分隔字符串
WITH split_genres AS (
  SELECT 
    id, 
    genre, 
    SUBSTRING_INDEX(SUBSTRING_INDEX(genre, ',', n), ',', -1) AS single_genre
  FROM anime
  -- 这里的numbers表要包含足够多的数字,覆盖最多的流派数量
  JOIN (SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) numbers
  ON CHAR_LENGTH(genre) - CHAR_LENGTH(REPLACE(genre, ',', '')) >= n - 1
)
SELECT id, genre
FROM split_genres
WHERE single_genre IN ('Action', 'Comedy', 'Romance')
GROUP BY id, genre
HAVING COUNT(DISTINCT single_genre) = 3;

思路是把每条记录的流派拆成单独行,筛选出目标流派后,分组统计不同流派的数量等于3,就说明原记录同时包含所有三个流派。

优化建议:规范化数据库设计

如果经常需要做这种多流派的精确查询,最稳妥的方式是规范化你的数据库:

  1. 创建一个anime_genres关联表,字段为anime_id(关联动漫表的主键)和genre(单一流派)
  2. 每个动漫的每个流派单独存一行

这样查询会更高效,也避免了字符串操作的各种坑:

SELECT a.*
FROM anime a
JOIN anime_genres ag ON a.id = ag.anime_id
WHERE ag.genre IN ('Action', 'Comedy', 'Romance')
GROUP BY a.id
HAVING COUNT(DISTINCT ag.genre) = 3;

内容的提问来源于stack exchange,提问作者user9347721

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:27:26