使用 MySQL 连接三个表
Posted
技术标签:
【中文标题】使用 MySQL 连接三个表【英文标题】:Joining three tables using MySQL 【发布时间】:2011-04-12 04:39:24 【问题描述】:我有三个名为
的表**Student Table**
-------------
id name
-------------
1 ali
2 ahmed
3 john
4 king
**Course Table**
-------------
id name
-------------
1 physic
2 maths
3 computer
4 chemistry
**Bridge**
-------------
sid cid
-------------
1 1
1 2
1 3
1 4
2 1
2 2
3 3
3 4
4 1
4 2
现在显示学生姓名和他学习过的课程名称,
**Result**
---------------------------
Student Course
---------------------------
ahmed physic
ahmed maths
ahmed computer
ahmed chemistry
ali physic
ali maths
john computer
john chemistry
king physic
king maths
我构建以下查询
select s.name as Student, c.name as Course from student s, course c join bridge b on c.id = b.cid order by s.name
但它没有返回所需的结果...
如果我想找出谁是经理而不是其他人,那么规范化的形式是什么:
**employee**
-------------------
id name
-------------------
1 ali
2 king
3 mak
4 sam
5 jon
**manage**
--------------
mid eid
--------------
1 2
1 3
3 4
4 5
并且想要得到这个结果:
**result**
--------------------
Manager Staff
--------------------
ali king
ali mak
mak sam
sam jon
【问题讨论】:
在第一个结果中,您错误地为 ahmed 和 ali 设置了数据 我们有 4 个表:姓名、地址、电子邮件、电话 SELECT A.personID, B.address, C.emailID, D.mobnumber FROM name AS A INNER JOIN address AS B ON A.personID = B.personID INNER JOIN email AS C ON A.personID = C.personID INNER JOIN phone AS D ON A.personID = D.personID 这是假设 personID 存在于所有表中。此查询将显示人员 ID、地址、电子邮件、电话号码,其中人员 ID 在所有表中都相同,因为它是内部联接。希望这会有所帮助:) 【参考方案1】:使用 ANSI 语法,你如何加入表格会更清楚:
SELECT s.name as Student, c.name as Course
FROM student s
INNER JOIN bridge b ON s.id = b.sid
INNER JOIN course c ON b.cid = c.id
ORDER BY s.name
【讨论】:
@Muhammad:我们的答案是一样的,只是语法不同。如果您不了解ANSI
语法,那么值得您花时间学习它。它将帮助您避免像您将来犯的JOIN
错误。【参考方案2】:
简单使用:
select s.name "Student", c.name "Course"
from student s, bridge b, course c
where b.sid = s.sid and b.cid = c.cid
【讨论】:
见***.com/questions/13476029/… 很好很简单,但 FWIW 考虑以下博客重新使用这种语法:sqlblog.org/2009/10/08/bad-habits-to-kick-using-old-style-joins 如***.com/a/13476050/199364 中所述 不,不,不,不,不!不要再使用这种遗留的、古老的、超过 25 岁的连接语法了!使用 this answer!! 中的显式连接【参考方案3】:用于规范化表格
select e1.name as 'Manager', e2.name as 'Staff'
from employee e1
left join manage m on m.mid = e1.id
left join employee e2 on m.eid = e2.id
【讨论】:
m.mid = e1.id
和 m.eid = e2.id
的顺序重要吗?
@Pathros 不,在这些表达式中顺序无关紧要。【参考方案4】:
使用这个:
SELECT s.name AS Student, c.name AS Course
FROM student s
LEFT JOIN (bridge b CROSS JOIN course c)
ON (s.id = b.sid AND b.cid = c.id);
【讨论】:
这个答案没有为这个问题添加任何新内容,并且使用了奇怪的语法(如果不是简单的错误语法,如果这在 mysql 中甚至是有效的,我会感到惊讶)。 我不同意 AeroX。 Ansi 连接语法旨在消除旧式逗号/where 连接语法的问题。我正在查看 MySql 是否专门支持 ansi join 语法。【参考方案5】:SELECT *
FROM user u
JOIN user_clockits uc ON u.user_id=uc.user_id
JOIN clockits cl ON cl.clockits_id=uc.clockits_id
WHERE user_id = 158
【讨论】:
这个答案看起来与 5 年前已经给出的答案非常相似。您认为您的答案在哪些方面很重要,并且在现有答案中缺失?【参考方案6】:SELECT
employees.id,
CONCAT(employees.f_name," ",employees.l_name) AS 'Full Name', genders.gender_name AS 'Sex',
depts.dept_name AS 'Team Name',
pay_grades.pay_grade_name AS 'Band',
designations.designation_name AS 'Role'
FROM employees
LEFT JOIN genders ON employees.gender_id = genders.id
LEFT JOIN depts ON employees.dept_id = depts.id
LEFT JOIN pay_grades ON employees.pay_grade_id = pay_grades.id
LEFT JOIN designations ON employees.designation_id = designations.id
ORDER BY employees.id;
你可以像上面这个例子一样加入多个表。
【讨论】:
几年前已经有多个答案显示“加入多个表”。您的回答对讨论有何意义?【参考方案7】:查询连接两个以上的表:
SELECT ops.field_id, ops.option_id, ops.label
FROM engine4_user_fields_maps AS map
JOIN engine4_user_fields_meta AS meta ON map.`child_id` = meta.field_id
JOIN engine4_user_fields_options AS ops ON map.child_id = ops.field_id
WHERE map.option_id =39 AND meta.type LIKE 'outcomeresult' LIMIT 0 , 30
【讨论】:
几年前已经有多个答案显示“加入多个表”。您的回答对讨论有何意义?【参考方案8】:不要那样加入。这是一个非常非常糟糕的做法!!!它会降低获取大量数据的性能。例如,如果每个表中有 100 行,则数据库服务器必须获取 100x100x100 = 1000000
次。它必须获取1 million
次。为了克服这个问题,加入前两个可以获取结果的表以尽可能少的匹配(这取决于您的数据库模式)。在子查询中使用该结果,然后将其与第三个表连接并获取它。对于第一次加入 --> 100x100= 10000
次,假设我们得到 5 个匹配结果。然后我们将第三个表与结果连接起来 --> 5x100 = 500.
Total fetch = 10000+500 = 10200
times only。因此,性能上升了!!!
【讨论】:
【参考方案9】:只是在以前的答案中添加一个点,在 MySQL 中我们可以使用
table_factor syntax
或
joined_table syntax
mysql documentation
Table_factor 示例
SELECT prd.name, b.name
FROM products prd, buyers b
联接表示例
SELECT prd.name, b.name
FROM products prd
left join buyers b on b.bid = prd.bid;
仅供参考:请忽略连接表示例中的左连接没有多大意义(实际上我们会使用某种连接表将买家链接到产品表,而不是在产品表中保存买家 ID)。
【讨论】:
【参考方案10】:Query for three table join and limit set
SELECT * FROM (SELECT t1.follower_userid, t2.*, t3.login_thumb, t3.login_name,
t3.bio, t3.account_status, t3.gender
FROM videos t2
LEFT JOIN follower t1
ON t1.follower_userid = t2.user_id
LEFT JOIN videos_user t3
ON t1.follower_userid = t3.login_userid
WHERE t1.following_userid='$userid'
LIMIT $startpoint , $limit) AS ID
ORDER BY ID DESC
【讨论】:
【参考方案11】:连接三个表的查询,我们想要来自同一列的两个值,我们为连接中的每个表设置别名。相同的表名也声明为不同的名称。
const sql = `select p.ID,p.purchaseamount,urs.name as
buyername,pd.productname,
pd.amount,urs1.name as sellername
from purchases p
left join products pd on p.productid=pd.ID
left join users urs on p.userid=urs.ID
left join users urs1 on pd.userid=urs1.ID`
【讨论】:
以上是关于使用 MySQL 连接三个表的主要内容,如果未能解决你的问题,请参考以下文章
为啥对三个表的联合 mysql 查询比在不可能的 where 子句上连接更快?