Oracle 计算子查询中的不同记录
Oracle count distinct record within subquery
我有 3 张桌子
主题
CODE, SUBJECT_NAME , SESSION
100, MATHS , AM
101, MATHS - INTRO , AM
102, MATHS - ADVANCED , AM
200, ENGLISH , AM
201, ENGLISH - INTRO , AM
202, ENGLISH - BEGINNER, AM
203, ENGLISH - ADVANCED, AM
STUDENTS_SUBJECTS
ID, SUBJECT_CODE
2, 101
2, 102
1, 201
1, 203
3, 101
3, 102
学生
ID,PARENT_ID, STUDENT_NAME, CLASS_LEADER, INACTIVE, EXPERT
1 , 2 , ELSA , no , N , N
2 , 4 , STEVE , no , N , N
3 , 5 , MIKE , no , N , N
我的查询是这样的
SELECT t1.CODE,
t1.SUBJECT_NAME,
SUM (CASE WHEN ( (t2.CLASS_LEADER = 'no'
OR t2.CLASS_LEADER IS NULL)
AND t2.EXPERT IS NULL)
THEN 1 ELSE 0 END) AS "Average Student"
FROM subjects t1
LEFT OUTER JOIN (
select a.STUDENT_ID, a.PARENT_ID, a.STUDENT_NAME,
a.CLASS_LEADER, c.SUBJECT_CODE, a.INACTIVE, a.EXPERT
FROM students a
INNER JOIN students_subjects c
ON (a.STUDENT_ID = c.ID )
where (INACTIVE is null)
GROUP BY a.STUDENT_ID, a.PARENT_ID, a.STUDENT_NAME, a.CLASS_LEADER, c.SUBJECT_CODE, a.INACTIVE, a.EXPERT
) t2
ON substr(trim(t2.SUBJECT_CODE),1,2)= substr(trim(t1.CODE),1,2)
WHERE (t1.SESSION='AM')
GROUP BY t1.CODE, T1.SUBJECT_NAME
ORDER BY T1.CODE
我想得到的是class每个主科的上午班报名没有重复的学生人数。例如,每个报名参加 Maths - Intro & Maths Advanced 的学生只能在 Maths 科目下计算一次。
如果我 运行 子查询分别减去 select 语句中的 subject_code 并按语句分组,我设法获得了正确的值但是我不确定如何 return 加入查询时的正确值。
报告
CODE, SUBJECT_NAME, AVERAGE_STUDENT
100 MATHS 2
200 ENGLISH 1
谢谢。
您发布的查询包含很多无关的逻辑,这些逻辑似乎与您的明显任务无关。所以我忽略它并专注于简单地获取 "the number of students who signed up for the class for morning session under each major subject without the duplicates".
select major
, count(*)
from (
select distinct subj.major
, ss.id as student_id
from
( select code,
regexp_replace(subject_name, '^([A-Z]+)(.*)', '') major ,
from subjects
where session = 'AM'
) subj
join student_subjects ss
on ss.subject_code = subj.code
)
group by major
order by major
/
SUBJECTS 上的子查询使用正则表达式函数提取主题名称的前导元素作为主要元素。它适用于已发布的示例数据,但对于更复杂的名称可能会失败。不需要正则表达式:适当的数据模型会将主要主题与其子公司分开。
先推荐一下:
1) 将列 MAIN_SUBJECT_CODE 添加到 table 主题(如前所述)
2) table STUDENTS_SUBJECTS 中的列 ID 是指向 table STUDENT 的外键,因此更好的名称是 STUDENT_ID
3) 使用独特的机制来存储布尔值不要混合使用 'no' 和 'N'
首先查询所有学生订阅
请注意,我添加了缺失的列 main_subject_code 并调整了平均学生定义以获得一些结果。
SELECT su.CODE,
substr(trim(su.CODE),1,2)||'0' main_subject_code,
su.SUBJECT_NAME,
st.STUDENT_NAME,
CASE WHEN ( (st.CLASS_LEADER = 'no'
OR st.CLASS_LEADER IS NULL)
AND st.EXPERT = 'N' /*IS NULL*/)
THEN 1 ELSE 0 END AS "Average Student"
FROM subjects su
INNER JOIN students_subjects ss
ON su.code = ss.SUBJECT_CODE
INNER JOIN STUDENTS st
ON ss.ID /* STUDENT_ID */ = st.ID
;
CODE MAIN_SUBJECT_CODE SUBJECT_NAME STUDENT_NAME Average Student
101 100 MATHS - INTRO MIKE 1
101 100 MATHS - INTRO STEVE 1
102 100 MATHS - ADVANCED MIKE 1
102 100 MATHS - ADVANCED STEVE 1
201 200 ENGLISH - INTRO ELSA 1
203 200 ENGLISH - ADVANCED ELSA 1
剩下的很简单 - 在主要主题上分组并添加它的标题
with subsr as (
SELECT su.CODE,
substr(trim(su.CODE),1,2)||'0' main_subject_code,
su.SUBJECT_NAME,
st.STUDENT_NAME,
CASE WHEN ( (st.CLASS_LEADER = 'no'
OR st.CLASS_LEADER IS NULL)
AND st.EXPERT = 'N' /*IS NULL*/)
THEN 1 ELSE 0 END AS "Average Student"
FROM subjects su
INNER JOIN students_subjects ss
ON su.code = ss.SUBJECT_CODE
INNER JOIN STUDENTS st
ON ss.ID /* STUDENT_ID */ = st.ID
)
select
main_subject_code,
(select SUBJECT_NAME from SUBJECTS where CODE = main_subject_code) main_subject_name,
sum("Average Student") "Average Student"
from subsr
group by main_subject_code
order by main_subject_code;
MAIN_SUBJECT_CODE MAIN_SUBJECT_NAME Average Student
----------------- ------------------------- ---------------
100 MATHS 4
200 ENGLISH 2
我有 3 张桌子
主题
CODE, SUBJECT_NAME , SESSION
100, MATHS , AM
101, MATHS - INTRO , AM
102, MATHS - ADVANCED , AM
200, ENGLISH , AM
201, ENGLISH - INTRO , AM
202, ENGLISH - BEGINNER, AM
203, ENGLISH - ADVANCED, AM
STUDENTS_SUBJECTS
ID, SUBJECT_CODE
2, 101
2, 102
1, 201
1, 203
3, 101
3, 102
学生
ID,PARENT_ID, STUDENT_NAME, CLASS_LEADER, INACTIVE, EXPERT
1 , 2 , ELSA , no , N , N
2 , 4 , STEVE , no , N , N
3 , 5 , MIKE , no , N , N
我的查询是这样的
SELECT t1.CODE,
t1.SUBJECT_NAME,
SUM (CASE WHEN ( (t2.CLASS_LEADER = 'no'
OR t2.CLASS_LEADER IS NULL)
AND t2.EXPERT IS NULL)
THEN 1 ELSE 0 END) AS "Average Student"
FROM subjects t1
LEFT OUTER JOIN (
select a.STUDENT_ID, a.PARENT_ID, a.STUDENT_NAME,
a.CLASS_LEADER, c.SUBJECT_CODE, a.INACTIVE, a.EXPERT
FROM students a
INNER JOIN students_subjects c
ON (a.STUDENT_ID = c.ID )
where (INACTIVE is null)
GROUP BY a.STUDENT_ID, a.PARENT_ID, a.STUDENT_NAME, a.CLASS_LEADER, c.SUBJECT_CODE, a.INACTIVE, a.EXPERT
) t2
ON substr(trim(t2.SUBJECT_CODE),1,2)= substr(trim(t1.CODE),1,2)
WHERE (t1.SESSION='AM')
GROUP BY t1.CODE, T1.SUBJECT_NAME
ORDER BY T1.CODE
我想得到的是class每个主科的上午班报名没有重复的学生人数。例如,每个报名参加 Maths - Intro & Maths Advanced 的学生只能在 Maths 科目下计算一次。
如果我 运行 子查询分别减去 select 语句中的 subject_code 并按语句分组,我设法获得了正确的值但是我不确定如何 return 加入查询时的正确值。
报告
CODE, SUBJECT_NAME, AVERAGE_STUDENT
100 MATHS 2
200 ENGLISH 1
谢谢。
您发布的查询包含很多无关的逻辑,这些逻辑似乎与您的明显任务无关。所以我忽略它并专注于简单地获取 "the number of students who signed up for the class for morning session under each major subject without the duplicates".
select major
, count(*)
from (
select distinct subj.major
, ss.id as student_id
from
( select code,
regexp_replace(subject_name, '^([A-Z]+)(.*)', '') major ,
from subjects
where session = 'AM'
) subj
join student_subjects ss
on ss.subject_code = subj.code
)
group by major
order by major
/
SUBJECTS 上的子查询使用正则表达式函数提取主题名称的前导元素作为主要元素。它适用于已发布的示例数据,但对于更复杂的名称可能会失败。不需要正则表达式:适当的数据模型会将主要主题与其子公司分开。
先推荐一下:
1) 将列 MAIN_SUBJECT_CODE 添加到 table 主题(如前所述)
2) table STUDENTS_SUBJECTS 中的列 ID 是指向 table STUDENT 的外键,因此更好的名称是 STUDENT_ID
3) 使用独特的机制来存储布尔值不要混合使用 'no' 和 'N'
首先查询所有学生订阅
请注意,我添加了缺失的列 main_subject_code 并调整了平均学生定义以获得一些结果。
SELECT su.CODE,
substr(trim(su.CODE),1,2)||'0' main_subject_code,
su.SUBJECT_NAME,
st.STUDENT_NAME,
CASE WHEN ( (st.CLASS_LEADER = 'no'
OR st.CLASS_LEADER IS NULL)
AND st.EXPERT = 'N' /*IS NULL*/)
THEN 1 ELSE 0 END AS "Average Student"
FROM subjects su
INNER JOIN students_subjects ss
ON su.code = ss.SUBJECT_CODE
INNER JOIN STUDENTS st
ON ss.ID /* STUDENT_ID */ = st.ID
;
CODE MAIN_SUBJECT_CODE SUBJECT_NAME STUDENT_NAME Average Student
101 100 MATHS - INTRO MIKE 1
101 100 MATHS - INTRO STEVE 1
102 100 MATHS - ADVANCED MIKE 1
102 100 MATHS - ADVANCED STEVE 1
201 200 ENGLISH - INTRO ELSA 1
203 200 ENGLISH - ADVANCED ELSA 1
剩下的很简单 - 在主要主题上分组并添加它的标题
with subsr as (
SELECT su.CODE,
substr(trim(su.CODE),1,2)||'0' main_subject_code,
su.SUBJECT_NAME,
st.STUDENT_NAME,
CASE WHEN ( (st.CLASS_LEADER = 'no'
OR st.CLASS_LEADER IS NULL)
AND st.EXPERT = 'N' /*IS NULL*/)
THEN 1 ELSE 0 END AS "Average Student"
FROM subjects su
INNER JOIN students_subjects ss
ON su.code = ss.SUBJECT_CODE
INNER JOIN STUDENTS st
ON ss.ID /* STUDENT_ID */ = st.ID
)
select
main_subject_code,
(select SUBJECT_NAME from SUBJECTS where CODE = main_subject_code) main_subject_name,
sum("Average Student") "Average Student"
from subsr
group by main_subject_code
order by main_subject_code;
MAIN_SUBJECT_CODE MAIN_SUBJECT_NAME Average Student
----------------- ------------------------- ---------------
100 MATHS 4
200 ENGLISH 2