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
);
查询:
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'
正如您在小提琴中看到的那样,查询的结果仅缺少3种技能的限制.
我尝试了几种子查询的变化..连接等但没有效果.
Nik*_* B. 79
一种有点hacky的方法是对后果进行后处理GROUP_CONCAT:
substring_index(group_concat(s.title SEPARATOR ','), ',', 3) as skills
当然,这假设您的技能名称不包含逗号,并且其数量相当小.
一个功能请求用于GROUP_CONCAT支持一个明确的LIMIT条款是可惜还是没有得到解决.
更新:正如用户草莓所指出的那样,该表player_skills应该将元组(player_id, skill_id)作为其主键,否则该模式允许将相同的技能多次分配给玩家,在这种情况下group_concat将无法按预期工作.
小智 19
GROUP_CONCAT使用GLOBAL group_concat_max_len
GROUP_CONCAT()最大长度增加函数长度为1024个字符.
你可以做的是设置GLOBAL group_concat_max_len在mysql中 
SET GLOBAL group_concat_max_len = 1000000;
试试这个,它肯定会起作用.
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;
有一个更清洁的解决方案.把它包装在另一个SELECT声明中.
SELECT GROUP_CONCAT(id) FROM (
    SELECT DISTINCT id FROM people LIMIT 4
) AS ids;
/* Result 134756,134754,134751,134750 */
这是另一种解决方案.它包括一个解决关系的任意机制,并采用与你的略有不同的架构......
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;
http://sqlfiddle.com/#!2/34497/18
顺便提一下,如果你有一个表示层/应用程序级代码,那么考虑在那里做所有GROUP_CONCAT的东西.它更灵活.
| 归档时间: | 
 | 
| 查看次数: | 58519 次 | 
| 最近记录: |