多个INNER JOIN子查询sql
Posted
技术标签:
【中文标题】多个INNER JOIN子查询sql【英文标题】:Multiple INNER JOIN subqueries sql 【发布时间】:2014-02-24 01:24:24 【问题描述】:我有以下查询来自这篇帖子count number of items in a row in mysql,它计算了一个学生连续出现/缺席的次数。
SELECT
classlist.studentid,
student.name,
classStatus.name status,
COUNT(*) presentcnt
FROM
classlist
INNER JOIN student ON classlist.studentid=student.id
INNER JOIN classstatus ON classlist.presentid=classstatus.id
INNER JOIN (
SELECT
studentid,
max(CASE WHEN presentid=0 THEN id END) max_0,
max(CASE WHEN presentid=1 THEN id END) max_1
FROM classlist
GROUP BY studentid
) s
ON coalesce(classlist.id>least(max_0,max_1) AND classlist.id<=greatest(max_0,max_1),1) AND s.studentid=classlist.studentid
GROUP BY classlist.studentid
这按预期工作,
STUDENTID NAME STATUS PRESENTCNT
111 John Present 1
222 Kate Absent 2
333 Matt Present 5
我想扩展查询,以便有一列显示学生是否参加了课堂。
如果我运行一个独立的查询,我会得到我想要的结果
SELECT
classlist.studentid,
student.name,
participatedStatus.name status,
COUNT(*) participatedcnt
FROM
classlist
INNER JOIN student ON classlist.studentid=student.id
INNER JOIN participatedStatus ON classlist.participatedid=participatedStatus.id
INNER JOIN (
SELECT
studentid,
max(CASE WHEN participatedid=0 THEN id END) max_0,
max(CASE WHEN participatedid=1 THEN id END) max_1
FROM classlist
group by studentid
) s
ON coalesce(classlist.id>least(max_0,max_1)
AND classlist.id<=greatest(max_0,max_1),1)
AND s.studentid=classlist.studentid
group by classlist.studentid
STUDENTID NAME STATUS PARTICIPATEDCNT
111 John Yes 1
222 Kate No 2
333 Matt Yes 2
但是我想将它们合并到一个查询中,这样我就得到了
STUDENTID NAME STATUS PRESENTCNT STATUS2 PARTICIPATEDCNT
111 John Present 1 Yes 1
222 Kate Absent 2 No 2
333 Matt Present 5 Yes 2
当我选择 count * 时,我对如何实现这一点感到困惑,我该如何实现这一点?
我使用的数据样本位于this fiddle 及以下
CREATE TABLE classlist
(`id` int, `studentid` int, `subjectid` int, `presentid` int, `participatedid` int);
CREATE TABLE student
(`id` int, `name` varchar(4));
CREATE TABLE subject
(`id` int, `name` varchar(4));
CREATE TABLE classStatus
(`id` int, `name` varchar(8));
CREATE TABLE participatedStatus
(`id` int, `name` varchar(8));
INSERT INTO classlist (`id`, `studentid`, `subjectid`, `presentid`, `participatedid`)
VALUES (1, 111, 1, 1, 0), (2, 222, 3, 0, 0), (3, 333, 2, 1, 0), (4, 111, 4, 0, 0), (5, 111, 1, 1, 0), (6, 222, 3, 0, 0), (7, 333, 2, 1, 1), (8, 111, 4, 0, 0), (9, 111, 4, 0, 0), (10, 111, 4, 0, 0), (11, 111, 1, 1, 1), (12, 333, 3, 1, 0), (13, 333, 2, 1, 1), (14, 333, 3, 1, 1);
INSERT INTO student (`id`, `name`)
VALUES (111, 'John'),(222, 'Kate'),(333, 'Matt');
INSERT INTO subject (`id`, `name`)
VALUES (1, 'MATH'),(2, 'ENG'),(3, 'SCI'),(4, 'GEO');
INSERT INTO classStatus (`id`, `name`)
VALUES (0, 'Absent'), (1, 'Present');
INSERT INTO participatedStatus (`id`, `name`)
VALUES (0, 'No'),(1, 'Yes');
【问题讨论】:
我不确定我是否跟随。您想知道学生既在场又专心的连续课程数量?因此,例如,如果一个学生连续上了 5 节课,但在第 4 节课中注意力不集中,那将注册为“3,1”? 【参考方案1】:SELECT
studid,
studname,
status,
presentcnt,
status1,
participatedcnt FROM
(SELECT
classlist.studentid studid,
student.name studname,
classStatus.name status,
COUNT(*) presentcnt
FROM
classlist
INNER JOIN student ON classlist.studentid=student.id
INNER JOIN classstatus ON classlist.presentid=classstatus.id
INNER JOIN (
SELECT
studentid,
max(CASE WHEN presentid=0 THEN id END) max_0,
max(CASE WHEN presentid=1 THEN id END) max_1
FROM classlist
GROUP BY studentid
) s
ON coalesce(classlist.id>least(max_0,max_1) AND classlist.id<=greatest(max_0,max_1),1) AND s.studentid=classlist.studentid
GROUP BY classlist.studentid)x
JOIN
(SELECT
classlist.studentid,
student.name,
participatedStatus.name status1,
COUNT(*) participatedcnt
FROM
classlist
INNER JOIN student ON classlist.studentid=student.id
INNER JOIN participatedStatus ON classlist.participatedid=participatedStatus.id
INNER JOIN (
SELECT
studentid,
max(CASE WHEN participatedid=0 THEN id END) max_0,
max(CASE WHEN participatedid=1 THEN id END) max_1
FROM classlist
group by studentid
) s
ON coalesce(classlist.id>least(max_0,max_1)
AND classlist.id<=greatest(max_0,max_1),1)
AND s.studentid=classlist.studentid
group by classlist.studentid)y
ON x.studid=y.studentid
Fiddle
【讨论】:
(1) 由 INNER JOIN 的子查询生成的两个表s
完全相同。那么,在性能方面,RDBMS 是否以某种方式对其进行了优化,只运行一次并存储结果,还是这个子查询运行两次? (2)如果它运行两次,以某种方式将这个子查询的结果存储在某个地方,在两个地方都使用它并优化查询性能是否有意义?实际上,有没有办法实际存储s
表?
好的,刚刚在this other *** answer 中找到了我对问题 (2) 的回答。总之,可以使用 WITH 语句来“存储”子查询的结果。问题 (1) 暂时没有答案以上是关于多个INNER JOIN子查询sql的主要内容,如果未能解决你的问题,请参考以下文章
INEXISTS的相关子查询用INNER JOIN 代替--性能优化