diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T94_FindTargetSumWays.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T94_FindTargetSumWays.java new file mode 100644 index 0000000..de12c41 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T94_FindTargetSumWays.java @@ -0,0 +1,59 @@ +package com.markilue.leecode.hot100; + +import org.junit.Test; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-04-10 12:49 + *@Description: + * TODO 力扣494 目标和: + * 给你一个整数数组 nums 和一个整数 target 。 + * 向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 : + * 例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。 + * 返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。 + *@Version: 1.0 + */ +public class T94_FindTargetSumWays { + + @Test + public void test() { + + int[] nums = {1, 1, 1, 1, 1}; + int target = 3; + System.out.println(findTargetSumWays(nums, target)); + + } + + + /** + * 思路:本质上就是一个背包问题: + * add-(sum-add)=target + * add=(sum+target)/2 + * 速度击败94.6% 内存击败50.13% 2ms + * @param nums + * @param target + * @return + */ + public int findTargetSumWays(int[] nums, int target) { + + int sum = 0; + for (int num : nums) { + sum += num; + } + if ((sum + target) % 2 != 0) return 0; + int mid = (sum + target) / 2; + if (mid < 0) return 0; + int[] dp = new int[mid + 1]; + dp[0] = 1; + + for (int i = 0; i < nums.length; i++) { + for (int j = mid; j >= nums[i]; j--) { + dp[j] += dp[j - nums[i]];//用这个数,不用这个数 + } + } + + return dp[mid]; + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T95_ConvertBST.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T95_ConvertBST.java new file mode 100644 index 0000000..07686dc --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T95_ConvertBST.java @@ -0,0 +1,46 @@ +package com.markilue.leecode.hot100; + +import com.markilue.leecode.tree.TreeNode; +import org.junit.Test; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-04-10 13:02 + *@Description: + * TODO 力扣538 把二叉搜索树转换为累加树: + * 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 + * 提醒一下,二叉搜索树满足下列约束条件: + * 节点的左子树仅包含键 小于 节点键的节点。 + * 节点的右子树仅包含键 大于 节点键的节点。 + * 左右子树也必须是二叉搜索树。 + *@Version: 1.0 + * + */ +public class T95_ConvertBST { + + @Test + public void test() { + + } + + int sum = 0; + + /** + * 后续遍历:递归法 + * 速度击败100% 内存击败85.25% 0ms + */ + + public TreeNode convertBST(TreeNode root) { + if (root == null) { + return null; + } + convertBST(root.right); + sum += root.val; + root.val = sum; + convertBST(root.left); + return root; + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T96_DiameterOfBinaryTree.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T96_DiameterOfBinaryTree.java new file mode 100644 index 0000000..22d34ac --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T96_DiameterOfBinaryTree.java @@ -0,0 +1,40 @@ +package com.markilue.leecode.hot100; + +import com.markilue.leecode.tree.TreeNode; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-04-10 13:17 + *@Description: + * TODO 力扣543 二叉树的直径: + * 给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。 + *@Version: 1.0 + */ +public class T96_DiameterOfBinaryTree { + + + int max = 0; + + /** + * 思路:就是计算最多一条链路上的节点数目 + * 速度击败100% 内存击败79.29% 递归法 + * @param root + * @return + */ + public int diameterOfBinaryTree(TreeNode root) { + sub(root); + return max; + } + + public int sub(TreeNode root) { + if (root == null) { + return 0; + } + int left = sub(root.left); + int right = sub(root.right); + max = Math.max(max, left + right); + return Math.max(left, right) + 1; + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T97_SubarraySum.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T97_SubarraySum.java new file mode 100644 index 0000000..04bfbe2 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T97_SubarraySum.java @@ -0,0 +1,116 @@ +package com.markilue.leecode.hot100; + +import org.junit.Test; + +import java.util.HashMap; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-04-10 13:28 + *@Description: + * TODO 力扣560 合为k的子数组: + * 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。 + *@Version: 1.0 + */ +public class T97_SubarraySum { + + @Test + public void test() { + int[] nums = {100,1,2,3,100,1,2,3,4}; + System.out.println(subarraySum1(nums, 3)); + } + + /** + * 思路:滑动窗口法(维护一个窗口内总和为k的窗口) + * 有问题:因为数组里面有负数的情况,这个判断就是有问题的 + * @param nums + * @param k + * @return + */ + public int subarraySum(int[] nums, int k) { + if (nums.length == 1 && nums[0] == k) { + return 1; + } + + int result = 0; + int cur = nums[0]; + int left = 0; + int right = 1; + + while (left <= right && right <= nums.length) { + if (cur == k && left != right) { + result++; + } + if (left == nums.length) break; + if (right < nums.length) { + cur += nums[right++]; + } else { + cur -= nums[left++];//到终点了,直接缩小窗口 + } + + + while (left < right && cur > k) { + + cur -= nums[left++]; + } + } + + return result; + + } + + + /** + * 官方前缀和+hash优化: + * 时间复杂度O(n) + * 速度击败53.66% 内存击败29.86% 24ms + * @param nums + * @param k + * @return + */ + public int subarraySum1(int[] nums, int k) { + int count = 0, pre = 0; + HashMap mp = new HashMap<>();// + mp.put(0, 1); + for (int i = 0; i < nums.length; i++) { + pre += nums[i]; + if (mp.containsKey(pre - k)) { + count += mp.get(pre - k); + } + mp.put(pre, mp.getOrDefault(pre, 0) + 1); + } + return count; + } + + + /** + * 官方最快: + * 速度击败92.3% 内存击败40.6% 21ms + * @param nums + * @param k + * @return + */ + public int subarraySum2(int[] nums, int k) { + HashMap map = new HashMap<>(); + map.put(0,1); + int res = 0; + int sum = 0; + for(int i = 0;i < nums.length; i++){ + sum+=nums[i]; + if(map.containsKey(sum - k)){ + res+=map.get(sum - k); + + } + if(map.containsKey(sum)){ + map.put(sum,map.get(sum)+1); + }else{ + map.put(sum, 1); + } + } + return res; + } + + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/sql/SQLPractice.sql b/Leecode/src/main/java/com/markilue/leecode/sql/SQLPractice.sql new file mode 100644 index 0000000..d04b973 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/sql/SQLPractice.sql @@ -0,0 +1,719 @@ +use sqlpractice; + +# 学生表Student +create table Student +( + SId varchar(10), + Sname varchar(10), + Sage datetime, + Ssex varchar(10) +); +insert into Student +values ('01', '赵雷', '1990-01-01', '男'); +insert into Student +values ('02', '钱电', '1990-12-21', '男'); +insert into Student +values ('03', '孙风', '1990-05-20', '男'); +insert into Student +values ('04', '李云', '1990-08-06', '男'); +insert into Student +values ('05', '周梅', '1991-12-01', '女'); +insert into Student +values ('06', '吴兰', '1992-03-01', '女'); +insert into Student +values ('07', '郑竹', '1989-07-01', '女'); +insert into Student +values ('09', '张三', '2017-12-20', '女'); +insert into Student +values ('10', '李四', '2017-12-25', '女'); +insert into Student +values ('11', '李四', '2017-12-30', '女'); +insert into Student +values ('12', '赵六', '2017-01-01', '女'); +insert into Student +values ('13', '孙七', '2018-01-01', '女'); + +# 科目表 +create table Course +( + CId varchar(10), + Cname nvarchar(10), + TId varchar(10) +); +insert into Course +values ('01', '语文', '02'); +insert into Course +values ('02', '数学', '01'); +insert into Course +values ('03', '英语', '03'); + +# 教师表 +create table Teacher +( + TId varchar(10), + Tname varchar(10) +); +insert into Teacher +values ('01', '张三'); +insert into Teacher +values ('02', '李四'); +insert into Teacher +values ('03', '王五'); + +# 成绩表SC +create table SC +( + SId varchar(10), + CId varchar(10), + score decimal(18, 1) +); +insert into SC +values ('01', '01', 80); +insert into SC +values ('01', '02', 90); +insert into SC +values ('01', '03', 99); +insert into SC +values ('02', '01', 70); +insert into SC +values ('02', '02', 60); +insert into SC +values ('02', '03', 80); +insert into SC +values ('03', '01', 80); +insert into SC +values ('03', '02', 80); +insert into SC +values ('03', '03', 80); +insert into SC +values ('04', '01', 50); +insert into SC +values ('04', '02', 30); +insert into SC +values ('04', '03', 20); +insert into SC +values ('05', '01', 76); +insert into SC +values ('05', '02', 87); +insert into SC +values ('06', '01', 31); +insert into SC +values ('06', '03', 34); +insert into SC +values ('07', '02', 89); +insert into SC +values ('07', '03', 98); + + +#TODO 1、查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数 + +select Student.sid, sname, sage, Ssex, s1, s2 +from student + join + (select t1.SId, s1, s2 + from (select SId, score s1 + from sc + where CId = '01') t1 + join + (select SId, score s2 + from sc + where CId = '02') t2 on t1.SId = t2.SId and t1.s1 > t2.s2) t3 on Student.SId = t3.SId; + +#TODO 2.1、查询同时存在" 01 "课程和" 02 "课程的情况 +select t1.SId, s1, s2 +from (select SId, score s1 + from sc + where CId = '01') t1 + join + (select SId, score s2 + from sc + where CId = '02') t2 on t1.SId = t2.SId; + +#TODO 2.2、查询存在" 01 "课程但可能不存在" 02 "课程的情况(不存在时显示为 null ) +select t1.sid, s1, s2 +from (select SId, score s1 + from sc + where CId = '01') t1 + left join (select SId, score s2 + from sc + where CId = '02') t2 on t1.SId = t2.SId; + + +#TODO 2.3、查询不存在" 01 "课程但存在" 02 "课程的情况 +select t2.sid, s1, s2 +from (select SId, score s1 + from sc + where CId = '01') t1 + right join (select SId, score s2 + from sc + where CId = '02') t2 on t1.SId = t2.SId; + +#TODO 3、查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩 +-- 查询平均成绩大于等于 60 分的同学 +select SId, sum(score) / count(score) avg +from sc +group by sid +having avg > 60; + +-- 查询这些学生的相关信息 +select t1.sid, Sname, avg +from student + right join (select SId, sum(score) / count(score) avg + from sc + group by sid + having avg > 60) t1 on Student.SId = t1.SId; + +#TODO 4、查询在 SC 表存在成绩的学生信息 +-- 存在成绩+去重 +select sid +from sc +where score is not null +group by sid; +-- 查询对应的信息 +select t1.sid, Sname, Sage, Ssex +from student + right join (select sid + from sc + where score is not null + group by sid) t1 on Student.SId = t1.SId; + +#TODO 5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null ) +-- 查询有成绩的 +select sid, count(score) c1, sum(score) s1 +from sc +group by sid; + +select Student.sid, sname, c1, s1 +from student + left join(select sid, count(score) c1, sum(score) s1 + from sc + group by sid) t1 on Student.sid = t1.SId; + +#TODO 6、查有成绩的学生信息 +-- 有成绩的学生 +select distinct(sid) +from sc +where score is not null; +-- 查询对应的信息 +select Student.sid, Student.sname, Student.sage, ssex +from student + right join (select distinct(sid) sid + from sc + where score is not null) t1 on Student.SId = t1.SId; + +#TODO 7、查询「李」姓老师的数量 +select count(TId) +from Teacher +where Tname like '李%'; + +#TODO 8、查询学过「张三」老师授课的同学的信息 + +-- 张三老师教过的课 +select cid, t.TId +from Course + join + (select tid, tname from teacher where tname = '张三') t on Course.TId = t.TId; + +-- 张三老师教过的课的学生 +select sid, t2.CId +from sc + join (select cid, t.TId + from Course + join + (select tid, tname from teacher where tname = '张三') t on Course.TId = t.TId) t2 + on sc.CId = t2.CId; + +-- 详细信息 +select t3.sid, Sname, sage, Ssex +from student + join(select sid, t2.CId + from sc + join (select cid, t.TId + from Course + join + (select tid, tname from teacher where tname = '张三') t on Course.TId = t.TId) t2 + on sc.CId = t2.CId) t3 on Student.SId = t3.SId; + +#TODO 9、查询没有学全所有课程的同学的信息 + +-- 查询全部course的数目 +select count(cid) num +from course; + +-- 查询没有学全所有课程的同学 +select sid, count(cid) c1, num +from sc, + (select count(cid) num + from course) t2 +group by sid +having c1 < t2.num; + +-- 查询对应学生的信息 +select S.sid, sname, Sage, Ssex +from Student + right join (select sid, count(cid) c1, num + from sc, + (select count(cid) num + from course) t2 + group by sid + having c1 < t2.num) S on Student.SId = S.SId; + +#TODO 10、查询至少有一门课与学号为" 01 "的同学所学相同的同学的信息 + +-- 学号01同学所学 +SELECT CId +from sc +where SId = '01'; + +-- 所学相同 +select Student.sid, sname, Sage, Ssex +from Student +where SId in + (select distinct (sid) + from sc + join(SELECT CId + from sc + where SId = '01') t1 on sc.CId = t1.CId + where SC.SId != '01'); + +#TODO 11、查询和" 01 "号的同学学习的课程完全相同的其他同学的信息 + +-- 先join得到所有的相同的课 + +-- 计算所有课的数目和原本的数目是否相等 +select sc.sid +from sc + join(select CId + from sc + where SId = '01') t1 on sc.CId = t1.CId +where sid != '01' +group by SId +having count(sc.cid) = (select count(CId) + from sc + where SId = '01'); + +select * +from student +where Student.SId in (select sc.sid + from sc + join(select CId + from sc + where SId = '01') t1 on sc.CId = t1.CId + where sid != '01' + group by SId + having count(sc.cid) = (select count(CId) + from sc + where SId = '01')); + +#TODO 12、查询没学过"张三"老师讲授的任一门课程的学生姓名 + +-- 查询张三老师教过的课 +select cid +from course + join(select TId + from teacher + where Tname = '张三') t1 + on Course.TId = t1.TId; +-- 查询学过张三老师教过的课的学生 +select SId +from sc +where CId in (select cid + from course + join(select TId + from teacher + where Tname = '张三') t1 + on Course.TId = t1.TId); +-- 查询没有学过张三老师教过的课的学生 +select * +from student +where SId not in (select SId + from sc + where CId in (select cid + from course + where tid in (select TId + from teacher + where Tname = '张三'))); + +# TODO 13、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩 + +-- 查询两门及其以上不及格课程的同学的学号 +select sid, count(CId) c1 +from sc +where score < 60 +group by sid +having c1 >= 2; + +-- 查询这些人的平均成绩 +select sid, avg(score) avg +from sc +where SId in + (select sid + from sc + where score < 60 + group by sid + having count(CId) >= 2) +group by sid; +-- 查询全部 +select t1.sid, Sname, avg +from student + join + (select sid, avg(score) avg + from sc + where SId in + (select sid + from sc + where score < 60 + group by sid + having count(CId) >= 2) + group by sid) t1 on Student.SId = t1.SId; + +#TODO 14、检索" 01 "课程分数小于 60,按分数降序排列的学生信息 +-- 降序学生 +select sid, score +from sc +where CId = '01' + and score < 60 +order by score desc; + +select * +from Student + join + (select sid, score + from sc + where CId = '01' + and score < 60 + order by score desc) t1 on Student.SId = t1.SId; + +#TODO 15、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩 +select sid, CId, score, avg +from (select sid, + CId, + score, + avg(score) over (partition by sid) avg + from sc) t1 +order by avg desc; + + +#TODO 16、查询各科成绩最高分、最低分和平均分: +select cid, max(score), min(score), avg(score) +from sc +group by cid; + +#TODO 17.1、按各科成绩进行排序,并显示排名, Score 重复时保留名次空缺 + +-- 窗口函数 +select cid, sid, score, rank() over (partition by CId order by score desc) +from sc; + +-- 师兄非窗口函数法 +SELECT *, COUNT(*) +FROM sc a + LEFT JOIN + sc b + ON a.cid = b.cid AND a.score <= b.score +GROUP BY a.cid, a.sid, a.score +ORDER BY a.cid DESC, a.score DESC; + +#TODO 17.2、按各科成绩进行排序,并显示排名, Score 重复时合并名次 +-- 窗口函数 +select cid, sid, score, dense_rank() over (partition by CId order by score desc) +from sc; +-- 师兄非窗口函数法 (应该有问题) +SELECT *, COUNT(*) +FROM sc a + LEFT JOIN + sc b + ON a.cid = b.cid AND a.score < b.score +GROUP BY a.cid, a.sid, a.score +ORDER BY a.cid DESC, a.score DESC; + + +# TODO 17.3、查询学生的总成绩,并进行排名,总分重复时保留名次空缺 + +-- 非窗口函数法 +select t1.sid, t1.sum, count(*) rk +from (select sid, sum(score) sum + from sc + group by sid) t1 + left join + (select sid, sum(score) sum + from sc + group by sid) t2 on t1.sum <= t2.sum +group by t1.sid, t1.sum +order by t1.sum desc; + +-- 窗口函数法 +select sid, sum, rank() over (order by sum desc) rk +from (select sid, sum(score) sum + from sc + group by sid) t1; + +#TODO 17.4、 查询学生的总成绩,并进行排名,总分重复时不保留名次空缺 + +-- 窗口函数法 +select sid, sum, dense_rank() over (order by sum desc) rk +from (select sid, sum(score) sum + from sc + group by sid) t1; + +SET @crank = 0; +SELECT b.sid, b.a, @crank := @crank + 1 AS rank1 +FROM (SELECT sid, SUM(score) AS a FROM sc GROUP BY sid ORDER BY a DESC) b; + +#TODO 18.统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[60-0] 及所占百分比 + +select t1.cid,cname,you,liang,zhong,cha,you/total,liang/total,zhong/total,cha/total +from course + join + ( + select cid, + sum(if(score >= 85 and score < 100, 1, 0)) you, + sum(if(score >= 70 and score < 85, 1, 0)) liang, + sum(if(score >= 60 and score < 70, 1, 0)) zhong, + sum(if(score > 0 and score < 60, 1, 0)) cha, + count(score) total + from sc + group by cid + )t1 on Course.CId=t1.CId; + +-- 师兄写法 +SELECT sc.cid,c.cname, + SUM(CASE WHEN score>85 AND score<=100 THEN 1 ELSE 0 END) AS '[100-85]', + SUM(CASE WHEN score>70 AND score<=85 THEN 1 ELSE 0 END) AS '[85-70]', + SUM(CASE WHEN score>60 AND score<=70 THEN 1 ELSE 0 END) AS '[70-60]', + SUM(CASE WHEN score<60 THEN 1 ELSE 0 END) AS '[60-0]', + SUM(CASE WHEN score>85 AND score<=100 THEN 1 ELSE 0 END)/COUNT(1) AS '[100-85]百分比', + SUM(CASE WHEN score>70 AND score<=85 THEN 1 ELSE 0 END)/COUNT(1) AS '[85-70]百分比', + SUM(CASE WHEN score>60 AND score<=70 THEN 1 ELSE 0 END)/COUNT(1) AS '[70-60]百分比', + SUM(CASE WHEN score<60 THEN 1 ELSE 0 END)/COUNT(1) AS '[60-0]百分比' +FROM sc ,course c +WHERE sc.cid=c.cid +GROUP BY sc.cid; + +# TODO 19查询各科成绩前三名的记录 + +-- 窗口函数法 +select cid,sid,score,rk +from + ( + select cid,sid,score,rank() over (partition by cid order by score desc) rk + from sc + ) t1 +where rk<=3; + +-- 师兄非窗口函数写法 +SELECT cid,sid,score FROM sc a +WHERE (SELECT COUNT(1) FROM sc b WHERE a.cid=b.cid AND a.score<=b.score)<=3 +ORDER BY cid; + +#TODO 20.查询每门课程被选修的学生数 +select Course.cid,Cname,student_num +from course +left join + ( + select cid,count(sid) student_num + from sc + group by cid + ) t1 on Course.CId=t1.CId; + +#TODO 21 查询出只选修两门课程的学生学号和姓名 +select t1.sid,Sname +from student +join + ( + select sid,count(cid) num + from sc + group by sid + having num=2 + ) t1 on Student.SId=t1.SId; + +#TODO 22.查询男生、女生人数`student` +select sum(if(Ssex='男',1,0)) '男生数量',sum(if(Ssex='女',1,0)) '女生数量' +from student; + +SELECT Ssex,COUNT(*) num FROM student GROUP BY ssex; + +#TODO 23.查询名字中含有「风」字的学生信息 +select * +from student +where Sname like '%风%'; + +#TODO 24.查询同名同姓学生名单,并统计同名人数 + +select sname ,count(sid) num +from student +group by sname +having num>1; + +#TODO 25.查询 1990 年出生的学生名单 +select sid,sname,Sage +from student +where year(Sage)='1990'; + +SELECT * FROM student WHERE sage LIKE '1990%'; + +#TODO 26.查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列 + +select cid,avg(score) avg +from sc +group by cid +order by avg desc,cid; + +#TODO 27.查询平均成绩大于等于 85 的所有学生的学号、姓名和平均成绩 + +select t1.sid,sname,avg +from student +right join + ( + select sid,avg(score) avg + from sc + group by sid + having avg>=85 + ) t1 on Student.SId=t1.sid; + +#TODO 28.查询课程名称为「数学」,且分数低于 60 的学生姓名和分数 + +select t1.sid,Sname,score +from student +join + ( + select cid,SId,score + from sc + where cid= + ( + select cid + from Course + where Cname ='数学' + )and score<60 + ) t1 on Student.SId=t1.SId; + +#TODO 29.查询所有学生的课程及分数情况(存在学生没成绩,没选课的情况) + +select Student.sid,sname,ifnull(Cname,'无'),ifnull(score,0) +from student +left join + ( + select sid,sc.cid,cname,score + from sc,course + where sc.cid=Course.CId + )t1 on Student.SId=t1.SId; + +#TODO 30.查询任何一门课程成绩在 70 分以上的姓名、课程名称和分数 + +select sc.sid,sname,sc.cid,cname,score +from sc,course,student +where sc.CId=Course.CId and Student.SId=sc.SId and score>70; + +SELECT t3.sname,t2.cname,t1.score FROM + ( + (SELECT * FROM sc) t1 + JOIN + (SELECT cid,cname FROM course) t2 + JOIN + (SELECT sid,sname FROM student) t3 + ON t1.cid=t2.cid AND t1.sid=t3.sid + ) +WHERE t1.score > 70; + +#TODO 31.查询不及格的课程 +select sid,cid,score,(case when score<60 then 'fail' else 'success' end) result +from sc +where score<60; + +# TODO 32.查询课程编号为 01 且课程成绩在 80 分以上的学生的学号和姓名 +select sid,Sname +from Student +where sid in +(select sid +from sc +where cid='01'and score>=80); + +-- 也可以join获得具体的数 +SELECT student.`SId`,student.`Sname`,sc.`CId`,sc.`score` +FROM sc,student +WHERE sc.`SId`=student.`SId` AND sc.`CId`=01 AND sc.`score`>=80; + +#TODO 33.求每门课程的学生人数 +select cid,count(sid) num +from sc +group by cid; + +#TODO 34.成绩不重复,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩 +select student.sid, sname, sage, ssex,cid, score +from student +join + ( + select sid,cid,score + from sc + where CId + in (select CId + from course + where TId in(select TId from teacher where Tname='张三')) + having score=max(score) + ) t1 on Student.SId=t1.SId; + +SELECT t2.sid,t2.cid,MAX(t2.score) FROM + ( + (SELECT CId FROM course WHERE TId = (SELECT tid FROM teacher WHERE Tname='张三'))t1 + JOIN + (SELECT * FROM sc) t2 + ON t1.cid=t2.cid + ); + +#TODO 35.成绩有重复的情况下,查询选修「张三」老师所授课程的学生中,成绩最高的学生信息及其成绩 + +-- 本人的应该有没有重复都行 +select student.sid, sname, sage, ssex,cid, score +from student + join + ( + select sid,cid,score + from sc + where CId + in (select CId + from course + where TId in(select TId from teacher where Tname='张三')) + having score=max(score) + ) t1 on Student.SId=t1.SId; + +# TODO 36.查询不同课程成绩相同的学生的学生编号、课程编号、学生编号 +-- 窗口函数 +-- 查询不同课程成绩相同的学生的学生编号 +select sid,score,CId,num +from + ( + select sid,score,cid,count(cid) over(partition by sid,score) num + from sc + )t1 +where num>1; + +-- 师兄不用窗口函数法(有四门课及以上的应该不对) +SELECT * FROM sc a +WHERE sid IN + (SELECT sid FROM sc + GROUP BY sid + HAVING (COUNT(*)=2 AND COUNT(DISTINCT score)=1) -- 有两门课有重复的情况 + OR (COUNT(*)=3 AND COUNT(DISTINCT score)<3)); -- 有三门课有重复的情况 + +-- 根据师兄的改进(去重前后不相等则有重复) +SELECT * FROM sc a +WHERE sid IN + (SELECT sid FROM sc + GROUP BY sid + HAVING COUNT(*) != COUNT(DISTINCT score)); + +#TODO 37.查询各学生的年龄,只按年份来算 + +SELECT sid,sname, YEAR(now())-YEAR(sage) age FROM student; + +#TODO 38.按照出生日期来算,当前月日 +SELECT sid,sname,TIMESTAMPDIFF(YEAR,sage,CURDATE()) age FROM student; + +-- 自己的本办法 +-- 判断年龄是否要-1 +select sid,sname ,year(now())-year(Sage)-if(month(now())-month(Sage)>0||(month(now())=month(Sage)&&day(now())>=day(Sage)),0,1) age +from student; + +#TODO 39.查询本周过生日的学生 +SELECT * FROM student WHERE WEEKOFYEAR(sage)=WEEKOFYEAR(CURDATE()) +