Person
可以有多条Degree
条记录。
人
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| firstName | varchar(60) | NO | | NULL | |
| lastName | varchar(100) | NO | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
Degree (编辑:为了简单起见,我隐藏了许多其他字段)
+----------+-------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| personID | int(11) | NO | MUL | NULL | |
| type | enum('PhD','MSE','MEng','MA') | NO | | NULL | |
+----------+-------------------------------+------+-----+---------+----------------+
在网页上,我想显示人员及其学位信息的列表(除了他们的类型之外,还有其他信息,我只是为了简单而没有包含它)。我相信这必须在N + 1个查询中完成。首先,选择所有具有学位的人的查询:
SELECT DISTINCT person.id
FROM person
JOIN degree ON degree.personID = person.id
然后在迭代每个结果时,直接查询他们的学位:
SELECT * FROM degree WHERE personID = :personID
然而,我的生活并非那么简单。我有两个额外的要求:
我正在努力将这些要求纳入查询。对于第一个要求,主查询需要事先知道用户具有的程度。我在这里需要一个子查询吗?
规则也需要以某种方式涉及主查询(以及加载度数的第二个查询)。
答案 0 :(得分:2)
您不需要多次查询。我假设您想要列表中的度数,例如:
SELECT p.id, group_concat(d.type)
FROM person p JOIN
degree d
ON d.personID = p.id
GROUP BY p.id
对于过滤,您可以使用having
。例如,以下内容总是会返回博士学位:
HAVING sum(d.degree = 'phd') > 0
" MA" /" PhD"问题增加了一些复杂性:
SELECT p.id,
(case when sum(d.degree = 'phd') > 0
then group_concat(case when d.type <> 'ma' then d.type end)
else group_concat(d.type)
end) as degrees
FROM person p JOIN
degree d
ON d.personID = p.id
GROUP BY p.id
答案 1 :(得分:0)
答案是基于Gordon Linoff的回答。
您可以使用Gordon的方法首先过滤掉人(在子查询中),然后在一个查询中加入他们的学位。
SELECT degree.*
FROM degree JOIN
(SELECT p.id as personID, group_concat(d.type) as deg_info
FROM person p JOIN
degree d
ON d.personID = p.id
GROUP BY p.id
HAVING INSTR(deg_info, 'MA')>0
AND INSTR(deg_info, 'phd')=0) filter ON degree.personId=filter.personID