Mariadb 如何使用SQL和多重连接或合并它们
我需要从表中检索事件,包括技能要求、用户参与和技能 对于一个项目,我有:Mariadb 如何使用SQL和多重连接或合并它们,mariadb,many-to-many,Mariadb,Many To Many,我需要从表中检索事件,包括技能要求、用户参与和技能 对于一个项目,我有: 用户表 从其他技能继承的技能表 包含用户技能的用户技能表 事件表 包含事件所需技能数量的事件技能表 包含用户参与事件的events_users表 我想检索所有事件,包括技能要求和用户参与 我的第一个想法是使用左连接: SELECT e.id, e.name, es.skill_id, s.name skill_name, es.quantity, eu.user_id, u.name user_nam
- 用户表
- 从其他技能继承的技能表
- 包含用户技能的用户技能表
- 事件表
- 包含事件所需技能数量的事件技能表
- 包含用户参与事件的events_users表
SELECT e.id, e.name, es.skill_id, s.name skill_name, es.quantity,
eu.user_id, u.name user_name, us.skill_id user_skill_id,
uss.name user_skill_name
FROM events e
LEFT JOIN events_skills es ON es.event_id = e.id
LEFT JOIN skills s ON s.id = es.skill_id
LEFT JOIN events_users eu ON eu.event_id = e.id
LEFT JOIN users u ON u.id = eu.user_id
LEFT JOIN users_skills us ON us.user_id = u.id
LEFT JOIN skills uss ON uss.id = us.skill_id;
id name skill_id skill_name quantity user_id user_name user_skill_id user_skill_name
1 eve1 2 ski2 3 1 use1 2 ski2
1 eve1 3 ski2-2 1 1 use1 2 ski2
1 eve1 2 ski2 3 2 use2 NULL NULL
1 eve1 3 ski2-2 1 2 use2 NULL NULL
2 eve2 NULL NULL NULL NULL NULL NULL NULL
2个不同的事件,第二个没有用户和技能。首先,有两个用户,第一个有一个技能,第二个没有技能,最后是两个技能要求
它工作“很好”,但它非常难看,我认为如果一个事件或用户有太多的技能,它可能会非常慢。
而且,每个事件都有很多行,很难对它们进行排序(如果我只想显示20个事件…)
为了改进,我想我可以分别加载所有技能,并删除表技能的两个左连接
但是,我可以将所有技能和数量合并到一个列中,将用户合并到其他列中吗?您是否有更好的解决方案/改进
id name skills users
1 eve1 2,3;3,1 1,2;2,NULL
2 eve2 NULL NULL
谢谢您的帮助。将技能和用户作为逗号分隔字符串的结果也正是我要做的。为此,请使用
GROUP\u CONCAT
select e.*, s.skills, u.users
from events e
left join
(
select event_id, group_concat(skill_id order by skill_id separator ',') as skills
from events_skills
group by event_id
) s on s.event_id = e.id
left join
(
select event_id, group_concat(user_id order by user_id separator ',') as users
from events_users
group by event_id
) u on u.event_id = e.id
order by e.id;
将技能和用户作为逗号分隔字符串的结果也正是我要做的。为此,请使用
GROUP\u CONCAT
select e.*, s.skills, u.users
from events e
left join
(
select event_id, group_concat(skill_id order by skill_id separator ',') as skills
from events_skills
group by event_id
) s on s.event_id = e.id
left join
(
select event_id, group_concat(user_id order by user_id separator ',') as users
from events_users
group by event_id
) u on u.event_id = e.id
order by e.id;
Thorsten建议的另一种方法:
select e.*,
( SELECT group_concat(skill_id order by skill_id separator ',')
from events_skills
WHERE event_id = e.id
) AS skills,
( SELECT group_concat(user_id order by user_id separator ',' )
from events_users
WHERE event_id = e.id
) AS users
from events e
order by e.id;
每个子查询都需要一个额外的连接来获取技能和用户的“名称”,而不是“id”
我建议您使用该技能的名称作为其id
当您有多个映射表时,请确保使用一对
id
作为主键
,并按相反顺序使用索引
。并且没有自动增量
。详细信息:托尔斯滕建议的另一种方法:
select e.*,
( SELECT group_concat(skill_id order by skill_id separator ',')
from events_skills
WHERE event_id = e.id
) AS skills,
( SELECT group_concat(user_id order by user_id separator ',' )
from events_users
WHERE event_id = e.id
) AS users
from events e
order by e.id;
每个子查询都需要一个额外的连接来获取技能和用户的“名称”,而不是“id”
我建议您使用该技能的名称作为其id
当您有多个映射表时,请确保使用一对
id
作为主键
,并按相反顺序使用索引
。并且没有自动增量
。详情:谢谢。性能如何?如果我理解的话,每行都会进行子选择。如果我有大的表,我想要所有事件表,它可能比“Thorsten Kettner”慢,但如果我只想要几行,它可能会更好?@Lortet-Oops,我忘了建议索引。见补充。至于哪个更快,两个都试试。(这可能取决于您使用的是哪个版本的MariaDB。)谢谢。性能如何?如果我理解的话,每行都会进行子选择。如果我有大的表,我想要所有事件表,它可能比“Thorsten Kettner”慢,但如果我只想要几行,它可能会更好?@Lortet-Oops,我忘了建议索引。见补充。至于哪个更快,两个都试试。(这可能取决于您使用的是哪个版本的MariaDB。)谢谢。性能如何?若我理解的话,连接选择只执行一次,但使用表中的所有数据。如果我有大的表,但我想要所有事件表,它可以比“Rock James”快,但如果我只需要几行,它可以慢一些?这在很大程度上取决于DBMS哪个版本更快。完美的DBMS将看到两个查询选择完全相同的数据,因此它将为这两个查询提供相同的执行计划。但是是的,很可能是我的查询在整个表上更快,而Rick的查询在几行上更快。试试看。除此之外,不要太担心性能。我不期望在运行查询时有很大的不同。因此,从外观上决定你更喜欢哪一个:-)没有一个比另一个更好,这只是两种不同的有效方法。@Lortet-在MySQL/MariaDB的旧版本中,LEFT JOIN(SELECT…
会重复计算子查询。真糟糕。但在今天的版本中,托尔斯滕和里克之间可能是一场较量。谢谢。性能如何?若我理解的话,连接选择只执行一次,但使用表中的所有数据。如果我有大的表,但我想要所有事件表,它可以比“Rock James”快,但如果我只需要几行,它可以慢一些?这在很大程度上取决于DBMS哪个版本更快。完美的DBMS将看到两个查询选择完全相同的数据,因此它将为这两个查询提供相同的执行计划。但是是的,很可能是我的查询在整个表上更快,而Rick的查询在几行上更快。试试看。除此之外,不要太担心性能。我不期望在运行查询时有很大的不同。因此,从外观上决定你更喜欢哪一个:-)没有一个比另一个更好,这只是两种不同的有效方法。@Lortet-在MySQL/MariaDB的旧版本中,LEFT JOIN(SELECT…
会重复计算子查询。真糟糕。但在今天的版本中,托尔斯滕和里克之间可能会有分歧。