GROUP_CONCAT有限制

d.r*_*aev 42 mysql group-concat

我有表player-s在许多一对多的关系与skill-s

目标是通过单个查询列出球员及其"前3名技能".

小提琴

create table player(
  id int primary key
);

create table skill(
  id int primary key,
  title varchar(100)
);

create table player_skills (
  id int primary key,
  player_id int,
  skill_id int,
  value int
);
Run Code Online (Sandbox Code Playgroud)

查询:

SELECT 
p.id,  
group_concat(s.title  SEPARATOR ', ') as skills

FROM player p
LEFT JOIN player_skills ps ON ps.player_id = p.id
LEFT JOIN skill s ON s.id = ps.skill_id

WHERE ps.value > 2
-- skills limit 3 some how ...
group by p.id 
order by s.id


-- expected result
-- player_ID, skills
-- 1 , 'one'
-- 2 , 'one'
-- 3 , 'two, three, four'
Run Code Online (Sandbox Code Playgroud)

正如您在小提琴中看到的那样,查询的结果仅缺少3种技能的限制.
我尝试了几种子查询的变化..连接等但没有效果.

Nik*_* B. 79

一种有点hacky的方法是对后果进行后处理GROUP_CONCAT:

substring_index(group_concat(s.title SEPARATOR ','), ',', 3) as skills
Run Code Online (Sandbox Code Playgroud)

当然,这假设您的技能名称不包含逗号,并且其数量相当小.

小提琴

一个功能请求用于GROUP_CONCAT支持一个明确的LIMIT条款是可惜还是没有得到解决.

更新:正如用户草莓所指出的那样,该表player_skills应该将元组(player_id, skill_id)作为其主键,否则该模式允许将相同的技能多次分配给玩家,在这种情况下group_concat将无法按预期工作.

  • 由于奇怪的(可能是多余的)PK,这应该是GROUP_CONCAT(DISTINCT ... (2认同)

小智 19

GROUP_CONCAT使用GLOBAL group_concat_max_len GROUP_CONCAT()最大长度增加函数长度为1024个字符.
你可以做的是设置GLOBAL group_concat_max_lenmysql中

SET GLOBAL group_concat_max_len = 1000000;
Run Code Online (Sandbox Code Playgroud)

试试这个,它肯定会起作用.


Luk*_*zda 11

如果您使用的是MariaDB 10.3.3+,则有可能:

支持 GROUP_CONCAT() 中的 LIMIT 子句( MDEV-11297 )

SELECT p.id,  
   GROUP_CONCAT(s.title ORDER BY title  SEPARATOR ', ' LIMIT 3) as skills
FROM player p
LEFT JOIN player_skills ps ON ps.player_id = p.id
LEFT JOIN skill s ON s.id = ps.skill_id
WHERE ps.value > 2
GROUP BY p.id 
ORDER BY s.id;
Run Code Online (Sandbox Code Playgroud)

db<>小提琴演示


Rom*_*ert 7

有一个更清洁的解决方案.把它包装在另一个SELECT声明中.

SELECT GROUP_CONCAT(id) FROM (
    SELECT DISTINCT id FROM people LIMIT 4
) AS ids;

/* Result 134756,134754,134751,134750 */
Run Code Online (Sandbox Code Playgroud)

  • MySQL 无法处理子查询内的 LIMIT。它已经让我发疯了很长一段时间:-/ (6认同)

Str*_*rry 5

这是另一种解决方案.它包括一个解决关系的任意机制,并采用与你的略有不同的架构......

SELECT a.player_id
     , GROUP_CONCAT(s.title ORDER BY rank) skills
  FROM
     ( SELECT x.*, COUNT(*) rank
         FROM player_skills x
         JOIN player_skills y 
           ON y.player_id = x.player_id
          AND (y.value > x.value
           OR (y.value = x.value AND y.skill_id <= x.skill_id))
        GROUP 
           BY player_id, value, skill_id
       HAVING COUNT(*) <= 3
     ) a
  JOIN skill s
    ON s.skill_id = a.skill_id
 GROUP 
    BY player_id;
Run Code Online (Sandbox Code Playgroud)

http://sqlfiddle.com/#!2/34497/18

顺便提一下,如果你有一个表示层/应用程序级代码,那么考虑在那里做所有GROUP_CONCAT的东西.它更灵活.