# 前言

  • 过于草率地相信直觉的判断了,作为一个猜想是需要验证的,想当然才是根源
  • 执行力不够,脑袋里产生想法之后一定要立即马上去验证,时间长了就忘了!!(最次也得上备忘录)
  • 对于连表的理解有欠缺
  • sql语句多学多看,多查,终身学习,不要被其他的边边角角占据了头脑,保持敏锐!
  • 对于where in和inner join,not in 和left join之间的转化关系有进一步了解
  • 前几名的问题,使用group_concat 和 find_in_set的形式可以方便地解决问题
  • 周的生日的问题,年份必须转化,不然只会是错误的结果
  • case when 的用法,常见于行和列的转化
  • MySQL里没有排名函数,所以使用定义的方式就尤为重要,尤其是不保留排名的方式,必须要3个变量

# Update Join

update table_name_1
inner join table_name_2 on table_name_1.id = table_name_2.uid
inner join table_name_3 on table_name_3.id = table_name_1.tid
set *** = ***
where ***

# Delete Join

DELETE a FROM t1 a LEFT JOIN (SELECT min(info_id) AS infoId
FROM t1
GROUP BY form_id) b ON a.info_id = b.infoId WHERE b.infoId is NULL

# in 和 exists

in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询,一直以来认为exists比in效率高的说法是不准确的。如果查询的两个表大小相当,那么用in和exists差别不大;如果两个表中一个较小一个较大,则子查询表大的用exists,子查询表小的用in;

例如:表A(小表),表B(大表)

select * from A where cc in(select cc from B)  -->效率低,用到了A表上cc列的索引;

select * from A where exists(select cc from B where cc=A.cc)  -->效率高,用到了B表上cc列的索引。
相反的:

select * from B where cc in(select cc from A)  -->效率高,用到了B表上cc列的索引

select * from B where exists(select cc from A where cc=B.cc)  -->效率低,用到了A表上cc列的索引。

# not in 和not exists

not in 逻辑上不完全等同于not exists,如果你误用了not in,小心你的程序存在致命的BUG,请看下面的例子:

create table ##t1(c1 int,c2 int);

create table ##t2(c1 int,c2 int);

insert into ##t1 values(1,2);

insert into ##t1 values(1,3);

insert into ##t2 values(1,2);

insert into ##t2 values(1,null);

select * from ##t1 where c2 not in(select c2 from ##t2);  -->执行结果:无

select * from ##t1 where not exists(select 1 from ##t2 where ##t2.c2=##t1.c2)  -->执行结果:1  3

正如所看到的,not in出现了不期望的结果集,存在逻辑错误。如果看一下上述两个select 语句的执行计划,也会不同,后者使用了hash_aj,所以,请尽量不要使用not in(它会调用子查询),而尽量使用not exists(它会调用关联子查询)。如果子查询中返回的任意一条记录含有空值,则查询将不返回任何记录。如果子查询字段有非空限制,这时可以使用not in,并且可以通过提示让它用hasg_aj或merge_aj连接。

如果查询语句使用了not in,那么对内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比not in 要快。

  • 说多了都是泪啊

# 获取表中某字段包含某字符串的数据

SELECT * FROM `表名` WHERE LOCATE('关键字', 字段名)
  • locate函数的用法

# 连续范围的问题

## 创建测试表
CREATE TABLE `test_number` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `number` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '数字',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


## 创建测试数据
insert into test_number values(1,1);
insert into test_number values(2,2);
insert into test_number values(3,3);
insert into test_number values(4,5);
insert into test_number values(5,7);
insert into test_number values(6,8);
insert into test_number values(7,10);
insert into test_number values(8,11);

SELECT min(number) start_range, max(number) end_range
FROM (SELECT number, rn, number - rn diff
      FROM (SELECT number, @number := @number + 1 rn
            FROM test_number,
                 (SELECT @number := 0) AS number) b) c
GROUP BY diff;

# 签到问题

## 创建参考表(模拟数据需要用到)
CREATE TABLE `test_nums` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='参考表';
## 模拟数据,插入 1-1000 连续数据.
create PROCEDURE test()
  BEGIN
    DECLARE i int DEFAULT 1;
    WHILE (i < 1000) DO INSERT INTO test_nums VALUES (i);
      SET i = i + 1;
    END WHILE;
  END;
CALL test();
DROP PROCEDURE test;

## 创建测试表
CREATE TABLE `test_sign_history` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '用户ID',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '签到时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='签到历史表';

## 创建测试数据
insert into test_sign_history(uid,create_time)
select ceil(rand()*10000),str_to_date('2016-12-11','%Y-%m-%d')+interval ceil(rand()*10000) minute
from test_nums where id<500;

## 统计每天的每小时用户签到情况
SELECT
       tmp.h,
       sum(CASE WHEN tmp.d = '20161211' THEN tmp.c ELSE 0 END ) as 11sign,
       sum(CASE WHEN tmp.d = '20161212' THEN tmp.c ELSE 0 END ) as 12sign,
       sum(CASE WHEN tmp.d = '20161213' THEN tmp.c ELSE 0 END ) as 13sign,
       sum(CASE WHEN tmp.d = '20161214' THEN tmp.c ELSE 0 END ) as 14sign,
       sum(CASE WHEN tmp.d = '20161215' THEN tmp.c ELSE 0 END ) as 15sign,
       sum(CASE WHEN tmp.d = '20161216' THEN tmp.c ELSE 0 END ) as 16sign,
       sum(CASE WHEN tmp.d = '20161217' THEN tmp.c ELSE 0 END ) as 17sign
FROM
(select hour(create_time) h,date_format(create_time,'%Y%m%d') as d,count(*) c
FROM test_sign_history group BY h,d) tmp
GROUP BY tmp.h ORDER BY tmp.h;

## 统计每天的每小时用户签到情况(当某个小时没有数据时,显示0)
## 主要在于使用了辅助表,使用它用来作为left join 的主表
SELECT
       tmp.h,
       sum(CASE WHEN tmp.d = '20161211' THEN tmp.c ELSE 0 END ) as 11sign,
       sum(CASE WHEN tmp.d = '20161212' THEN tmp.c ELSE 0 END ) as 12sign,
       sum(CASE WHEN tmp.d = '20161213' THEN tmp.c ELSE 0 END ) as 13sign,
       sum(CASE WHEN tmp.d = '20161214' THEN tmp.c ELSE 0 END ) as 14sign,
       sum(CASE WHEN tmp.d = '20161215' THEN tmp.c ELSE 0 END ) as 15sign,
       sum(CASE WHEN tmp.d = '20161216' THEN tmp.c ELSE 0 END ) as 16sign,
       sum(CASE WHEN tmp.d = '20161217' THEN tmp.c ELSE 0 END ) as 17sign
FROM
     (SELECT b.h,tsh.d,tsh.c
     FROM (SELECT id as h FROM test_nums WHERE id <= 24) b
     LEFT JOIN
     (select hour(create_time) h,date_format(create_time,'%Y%m%d') as d,count(*) c
      FROM test_sign_history group BY h,d) tsh ON b.h = tsh.h
     ) tmp
GROUP BY tmp.h ORDER BY tmp.h;

## 统计每天的用户签到数据和每天的增量数据
## 自己想的写法
SELECT t.d, t.cnt, t.cnt - @rown AS increase, @rown := t.cnt
FROM (SELECT date_format(create_time, '%Y%m%d') AS d, count(*) AS cnt
            FROM test_sign_history
      GROUP BY d
      ORDER BY d) t,
     (SELECT @rown := 0) r;

## 参考写法
## 两种写法,思想不同而已
SELECT type,
       sum(CASE WHEN create_time = '2016-12-11' THEN c ELSE 0 END) 11Sign,
       sum(CASE WHEN create_time = '2016-12-12' THEN c ELSE 0 END) 12Sign,
       sum(CASE WHEN create_time = '2016-12-13' THEN c ELSE 0 END) 13Sign,
       sum(CASE WHEN create_time = '2016-12-14' THEN c ELSE 0 END) 14Sign,
       sum(CASE WHEN create_time = '2016-12-15' THEN c ELSE 0 END) 15Sign,
       sum(CASE WHEN create_time = '2016-12-16' THEN c ELSE 0 END) 16Sign,
       sum(CASE WHEN create_time = '2016-12-17' THEN c ELSE 0 END) 17Sign
FROM (SELECT b.create_time, ifnull(b.c - c.c, 0) c, 'Increment' type
      FROM (SELECT date_format(create_time, '%Y-%m-%d') create_time, count(*) c
            FROM test_sign_history
            GROUP BY date_format(create_time, '%Y-%m-%d')) b
             LEFT JOIN (SELECT date_format(create_time, '%Y-%m-%d') create_time, count(*) c
                        FROM test_sign_history
                        GROUP BY date_format(create_time, '%Y-%m-%d')) c
               ON (b.create_time = c.create_time + INTERVAL 1 DAY)
      UNION ALL
      SELECT date_format(create_time, '%Y-%m-%d') create_time, count(*) c, 'Current'
      FROM test_sign_history
      GROUP BY date_format(create_time, '%Y-%m-%d')) a
GROUP BY type
ORDER BY CASE WHEN type = 'Current' THEN 1 ELSE 0 END DESC;


##模拟不同的用户签到了不同的天数
insert into test_sign_history(uid,create_time)
select uid,create_time + interval ceil(rand()*10) day from test_sign_history,test_nums
where test_nums.id <10 order by rand() limit 150;

## 统计签到天数相同的用户数量
SELECT date_format(create_time,'%Y%m%d') as d,count(DISTINCT uid) AS user_cnt
FROM test_sign_history GROUP BY d ORDER BY d;

## 统计每个用户的连续签到时间
## 属于连续问题的解决办法
SELECT tmp2.uid,max(tmp2.sign_last) FROM
       (
       SELECT tmp.uid, min(d) AS begin_date, max(d) AS end_date, datediff(max(d), min(d)) + 1 AS sign_last
        FROM (SELECT ud.uid, ud.d, datediff(ud.d, @time) AS diff, @time := @time + INTERVAL 1 DAY
              FROM (SELECT uid, date_format(create_time, '%Y-%m-%d') AS d
                    FROM test_sign_history
                    GROUP BY uid, d
                    ORDER BY uid, d) ud,
                   (SELECT @time := '2016-01-01') t) tmp
        GROUP BY tmp.uid, tmp.diff
       ) tmp2 GROUP BY tmp2.uid;

## 参考写法
SELECT *
FROM (SELECT d.*, @ggid := @cggid, @cggid := d.uid, if(@ggid = @cggid, @grank := @grank + 1, @grank := 1) grank
      FROM (SELECT uid, min(c.create_time) begin_date, max(c.create_time) end_date, count(*) count
            FROM (SELECT b.*,
                         @gid := @cgid,
                         @cgid := b.uid,
                         if(@gid = @cgid, @rank := @rank + 1, @rank := 1),
                         b.diff - @rank as flag
                  FROM (SELECT DISTINCT uid,
                                        date_format(create_time, '%Y-%m-%d') create_time,
                                        datediff(create_time, now())         diff
                        FROM test_sign_history
                        ORDER BY uid, create_time) b,
                       (SELECT @gid := 1, @cgid := 1, @rank := 1) AS a) c
            GROUP BY uid, flag
            ORDER BY uid, count(*) DESC) d,
           (SELECT @ggid := 1, @cggid := 1, @grank := 1) AS e)f
WHERE grank = 1;

MySQL2 (opens new window)

# MySQL的测试表

create table if not exists student(
  s_id varchar (20),
  s_name varchar (20) not null default '',
  s_birth varchar (20)not null default '',
  s_sex varchar (10) not null default '',
  primary key (s_id)
) ;

create table course(
  c_id varchar (20),
  c_name varchar (20)not null default '',
  t_id varchar (20)not null default '',
  primary key( c_id)
);

create table teacher(
  t_id varchar (20),
  t_name varchar (20)not null default '',
  primary key (t_id)
);

create table score(
  s_id varchar (20),
  c_id varchar (20),
  s_score int(3),
  primary key (s_id,c_id)
);

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('08' , '王菊' , '1990-01-20' , '女');

insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');

insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');

insert into Score values('01' , '01' , 80);
insert into Score values('01' , '02' , 90);
insert into Score values('01' , '03' , 99);
insert into Score values('02' , '01' , 70);
insert into Score values('02' , '02' , 60);
insert into Score values('02' , '03' , 80);
insert into Score values('03' , '01' , 80);
insert into Score values('03' , '02' , 80);
insert into Score values('03' , '03' , 80);
insert into Score values('04' , '01' , 50);
insert into Score values('04' , '02' , 30);
insert into Score values('04' , '03' , 20);
insert into Score values('05' , '01' , 76);
insert into Score values('05' , '02' , 87);
insert into Score values('06' , '01' , 31);
insert into Score values('06' , '03' , 34);
insert into Score values('07' , '02' , 89);
insert into Score values('07' , '03' , 98);

# 查询"01"课程比"02"课程成绩高的学生的信息及课程分数

  • 考虑02课程没选的的情况
    SELECT
    s.*,sc.s_score AS 01score,sc2.s_score AS 02score
    FROM student s INNER JOIN score sc ON s.s_id = sc.s_id AND sc.c_id = '01'
    LEFT JOIN score sc2 ON s.s_id = sc2.s_id AND sc2.c_id = '02'
    WHERE sc.s_score < sc2.s_score OR sc.s_score is NULL ;

SELECT student.*, a.s_score AS 01_score, b.s_score AS 02_score
FROM student
JOIN score a ON student.s_id = a.s_id AND a.c_id = '01'
LEFT JOIN score b ON student.s_id = b.s_id AND b.c_id = '02' OR b.c_id = NULL
WHERE a.s_score > b.s_score;

# 查询"01"课程比"02"课程成绩低的学生的信息及课程分数

SELECT student.*, a.s_score AS 01_score, b.s_score AS 02_score
FROM student
JOIN score a ON student.s_id = a.s_id AND a.c_id = '01' OR a.c_id = NULL
LEFT JOIN score b ON student.s_id = b.s_id AND b.c_id = '02'
WHERE a.s_score < b.s_score;

# 查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩

  • group by 之后,如果已经group by 了用以区分的id,那么其他所有的属性都是可以直接得出来的
    SELECT
    s.s_id,s.s_name,round(avg(sc.s_score),1) as avg_score
    FROM student s LEFT JOIN score sc on s.s_id = sc.s_id
    GROUP BY s.s_id,s.s_name HAVING avg(sc.s_score) >= 60;

SELECT student.s_id, student.s_name, tmp.avg_score
FROM student
JOIN (SELECT score.s_id, round(avg(score.s_score), 1)AS avg_score FROM score GROUP BY s_id)AS tmp
ON tmp.avg_score >= 60
WHERE student.s_id = tmp.s_id;

–答案2

SELECT student.s_id, student.s_name, round(avg(score.s_score), 1) AS avg_score
FROM student
JOIN score ON student.s_id = score.s_id
GROUP BY score.s_id
HAVING avg(score.s_score) >= 60;

# 查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩

– (包括有成绩的和无成绩的)
SELECT
s.s_id,s.s_name,ifnull(round(avg(sc.s_score),1),0) as avg_score
FROM student s LEFT JOIN score sc on s.s_id = sc.s_id
GROUP BY s.s_id,s.s_name HAVING avg(sc.s_score) < 60
or count(sc.s_score) = 0;

SELECT student.s_id, student.s_name, tmp.avg_score
FROM student
JOIN (SELECT score.s_id, round(avg(score.s_score), 1)AS avg_score FROM score GROUP BY s_id)AS tmp
ON tmp.avg_score < 60
WHERE student.s_id = tmp.s_id
UNION
SELECT s_id, s_name, 0 AS avg_score
FROM student
WHERE s_id NOT IN
(SELECT DISTINCT s_id FROM score);

–答案2

SELECT student.s_id, student.s_name, round(avg(score.s_score), 1) AS avg_score
FROM student
JOIN score ON student.s_id = score.s_id
GROUP BY score.s_id
HAVING avg(score.s_score) < 60
UNION
SELECT s_id, s_name, 0 AS avg_score
FROM student
WHERE s_id NOT IN
(SELECT DISTINCT s_id FROM score);

# 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩

SELECT s.s_id,s.s_name,count(DISTINCT sc.c_id) as num,sum(sc.s_score) as total
FROM student s LEFT JOIN score sc ON s.s_id = sc.s_id
GROUP BY s.s_id ORDER BY total DESC ;

SELECT student.s_id, student.s_name, count(score.c_id) AS total_count, sum(score.s_score)AS total_score
FROM student
LEFT JOIN score ON student.s_id = score.s_id
GROUP BY student.s_id ORDER BY total_score DESC ;

# 查询"李"姓老师的数量

SELECT count(1)
FROM teacher
WHERE t_name LIKE '李%';

# 查询学过"张三"老师授课的同学的信息

-- 这就是因为对于连表的概念还不够融汇贯通的表现
SELECT student.*
FROM student INNER JOIN
(SELECT sc.s_id
FROM score sc INNER JOIN course c ON sc.c_id = c.c_id
INNER JOIN teacher t ON c.t_id = t.t_id WHERE t.t_name= '张三') tmp
ON student.s_id = tmp.s_id;

SELECT student.*
FROM student INNER JOIN
score sc ON student.s_id = sc.s_id INNER JOIN course c ON sc.c_id = c.c_id
INNER JOIN teacher t ON c.t_id = t.t_id WHERE t.t_name= '张三';

SELECT *
FROM student
JOIN score ON student.s_id = score.s_id
WHERE score.c_id IN (SELECT course.c_id
FROM course
WHERE course.t_id IN (SELECT teacher.t_id FROM teacher WHERE teacher.t_name = '张三'));

–答案2

SELECT student.*
FROM student
JOIN score ON student.s_id = score.s_id
JOIN course ON course.c_id = score.c_id
JOIN teacher ON course.t_id = teacher.t_id AND t_name = '张三';

# 查询没学过"张三"老师授课的同学的信息

SELECT *
FROM student
WHERE s_id NOT IN (SELECT score.s_id
FROM score
WHERE score.c_id IN (SELECT course.c_id
FROM course
WHERE course.t_id =
(SELECT teacher.t_id FROM teacher WHERE teacher.t_name = '张三')));

SELECT student.*
FROM student LEFT JOIN
(SELECT sc.s_id
FROM score sc INNER JOIN course c ON sc.c_id = c.c_id
INNER JOIN teacher t ON c.t_id = t.t_id WHERE t.t_name= '张三') tmp
ON student.s_id = tmp.s_id WHERE tmp.s_id is NULL ;

–答案2

SELECT student.*
FROM student
LEFT JOIN (SELECT s_id
FROM score
JOIN course ON course.c_id = score.c_id
JOIN teacher ON course.t_id = teacher.t_id AND t_name = '张三')tmp ON student.s_id = tmp.s_id
WHERE tmp.s_id IS NULL;

# 查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息

SELECT *
FROM student
WHERE s_id IN (SELECT s_id FROM score WHERE c_id = 1)
AND s_id IN (SELECT s_id FROM score WHERE c_id = 2);

# 查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息

SELECT *
FROM student
WHERE s_id IN (SELECT s_id FROM score WHERE c_id = 1)
AND s_id NOT IN (SELECT s_id FROM score WHERE c_id = 2);

–答案2

SELECT student.*
FROM student
JOIN (SELECT s_id FROM score WHERE c_id = 1)tmp1 ON student.s_id = tmp1.s_id
LEFT JOIN (SELECT s_id FROM score WHERE c_id = 2)tmp2 ON student.s_id = tmp2.s_id
WHERE tmp2.s_id IS NULL;

# 查询没有学全所有课程的同学的信息

SELECT *
FROM student
WHERE s_id NOT IN (SELECT s_id FROM score GROUP BY s_id HAVING count(c_id) = (SELECT count(1) FROM course));

# 查询至少有一门课与学号为"01"的同学所学相同的同学的信息

-- 对于这种单个的条件的情况下,使用where in的方式,明显更加直接,如果有多个条件的情况下,使用join才是优势
SELECT DISTINCT student.* FROM student INNER JOIN score ON student.s_id = score.s_id WHERE score.c_id IN
(SELECT c_id FROM score WHERE s_id = '01') AND student.s_id <> '01';

SELECT *
FROM student
WHERE s_id <> 01
AND s_id IN (SELECT s_id FROM score WHERE c_id IN (SELECT c_id FROM score WHERE score.s_id = 01) GROUP BY s_id);

# 查询和"01"号的同学学习的课程完全相同的其他同学的信息

-- 使用了group_concat的知识,还以为能有什么新鲜的
SELECT s.*,tmp1.cids FROM student s INNER JOIN
(SELECT s_id,group_concat(c_id ORDER by c_id) as cids FROM score GROUP BY s_id ) tmp1
ON s.s_id = tmp1.s_id AND s.s_id <> '01'
WHERE tmp1.cids =
(SELECT group_concat(c_id ORDER by c_id) as cids FROM score WHERE s_id = '01' GROUP BY s_id );

SELECT student.*, tmp.course_id
FROM (SELECT s_id, group_concat(c_id) course_id
FROM score
GROUP BY s_id
HAVING s_id <> 1
AND course_id = (SELECT group_concat(c_id) course_id2 FROM score WHERE s_id = 1))tmp
JOIN student ON student.s_id = tmp.s_id;

# 查询没学过"张三"老师讲授的任一门课程的学生姓名

SELECT *
FROM student
WHERE s_id NOT IN (SELECT s_id
FROM score
JOIN (SELECT c_id FROM course WHERE t_id IN (SELECT t_id FROM teacher WHERE t_name = '张三'))tmp
ON score.c_id = tmp.c_id);

–答案2

SELECT student.*
FROM student
LEFT JOIN (SELECT s_id
FROM score
JOIN (SELECT c_id FROM course
JOIN teacher ON course.t_id = teacher.t_id AND t_name = '张三')tmp2
ON score.c_id = tmp2.c_id)tmp ON student.s_id = tmp.s_id
WHERE tmp.s_id IS NULL;

# 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩

-- 关于sum里面可以使用计算条件的方式,很多人都不知道
SELECT s.*,round(tmp.avg_score,1) as avg_score FROM student s INNER JOIN
(SELECT s_id,avg(s_score) as avg_score FROM score GROUP BY s_id HAVING sum(s_score < 60) >=2) tmp
ON s.s_id = tmp.s_id;

SELECT student.s_id, student.s_name, tmp.avg_score
FROM student
LEFT JOIN (SELECT s_id, round(AVG(score.s_score)) avg_score FROM score GROUP BY s_id)tmp
ON tmp.s_id = student.s_id
WHERE student.s_id IN (SELECT s_id FROM score WHERE s_score < 60 GROUP BY score.s_id HAVING count(s_id) > 1);

# 检索"01"课程分数小于60,按分数降序排列的学生信息

SELECT student.*, s_score
FROM student,
score
WHERE student.s_id = score.s_id
AND s_score < 60
AND c_id = '01'
ORDER BY s_score DESC;

# 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

-- 在查找的选项里还是可以有这种花式的写法的
SELECT s_id,
(SELECT s_score
FROM score
WHERE s_id = a.s_id
AND c_id = '01')AS 语文,
(SELECT s_score
FROM score
WHERE s_id = a.s_id
AND c_id = '02')AS 数学,
(SELECT s_score
FROM score
WHERE s_id = a.s_id
AND c_id = '03')AS 英语,
round(avg(s_score), 2) AS 平均分
FROM score a
GROUP BY s_id
ORDER BY 平均分 DESC;

–答案2
-- 尝试使用group_concat 的方式处理,外连接的一点模糊领域,要知道一个都连不到的情况下才会出现null

SELECT sc.s_id,avg(sc.s_score) as avg_score,group_concat(sc.s_score) FROM score sc
RIGHT JOIN course c ON c.c_id = sc.c_id
GROUP BY sc.s_id ORDER BY avg_score DESC ;

-- 由于如果一旦使用了group by sid的方式,那么各科的成绩将无法获取,所以使用left join 多个表的形式处理
SELECT a.s_id,
tmp1.s_score AS chinese,
tmp2.s_score AS math,
tmp3.s_score AS english,
round(avg(a.s_score), 2) AS avgScore
FROM score a
LEFT JOIN (SELECT s_id, s_score FROM score s1 WHERE c_id = '01')tmp1 ON tmp1.s_id = a.s_id
LEFT JOIN (SELECT s_id, s_score FROM score s2 WHERE c_id = '02')tmp2 ON tmp2.s_id = a.s_id
LEFT JOIN (SELECT s_id, s_score FROM score s3 WHERE c_id = '03')tmp3 ON tmp3.s_id = a.s_id
GROUP BY a.s_id, tmp1.s_score, tmp2.s_score, tmp3.s_score
ORDER BY avgScore DESC;

# 查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率 –及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90

-- 再次验证了sum里面的条件其实是可以直接等效为case when的,这样就非常方便了
SELECT sc.c_id,c.c_name,avg(sc.s_score) avg_score,max(sc.s_score) max_score,
min(sc.s_score) min_score,sum(s_score>=60)/count() AS pass_rate,
sum(s_score>=80 AND s_score<90)/count(
) AS good_rate
FROM score sc INNER JOIN course c on sc.c_id =c.c_id GROUP BY sc.c_id;

SELECT score.c_id AS '课程ID',
course.c_name AS '课程name',
max(s_score) AS '最高分',
min(s_score)AS '最低分',
round(avg(s_score), 2) '平均分',
round(sum(CASE WHEN s_score >= 60 THEN 1 ELSE 0 END) / sum(CASE WHEN s_score THEN 1 ELSE 0 END), 2)'及格率',
round(sum(CASE WHEN s_score >= 70 AND s_score < 80 THEN 1 ELSE 0 END) / sum(CASE WHEN s_score THEN 1 ELSE 0 END),
2)'中等率',
round(sum(CASE WHEN s_score >= 80 AND s_score < 90 THEN 1 ELSE 0 END) / sum(CASE WHEN s_score THEN 1 ELSE 0 END),
2)'优良率',
round(sum(CASE WHEN s_score >= 90 THEN 1 ELSE 0 END) / (SUM(CASE WHEN s_score THEN 1 ELSE 0 END)), 2)'优秀率'
FROM score
LEFT JOIN course ON score.c_id = course.c_id
GROUP BY score.c_id;

–答案2

SELECT course.c_id,
course.c_name,
tmp.maxScore,
tmp.minScore,
tmp.avgScore,
tmp.passRate,
tmp.moderate,
tmp.goodRate,
tmp.excellentRates
FROM course
JOIN (SELECT c_id,
max(s_score) AS maxScore,
min(s_score)AS minScore,
round(avg(s_score), 2) avgScore,
round(sum(CASE WHEN s_score >= 60 THEN 1 ELSE 0 END) / count(c_id), 2)passRate,
round(sum(CASE WHEN s_score >= 60 AND s_score < 70 THEN 1 ELSE 0 END) / count(c_id), 2) moderate,
round(sum(CASE WHEN s_score >= 70 AND s_score < 80 THEN 1 ELSE 0 END) / count(c_id), 2) goodRate,
round(sum(CASE WHEN s_score >= 80 AND s_score < 90 THEN 1 ELSE 0 END) / count(c_id),
2) excellentRates
FROM score
GROUP BY c_id)tmp ON tmp.c_id = course.c_id;

# 按各科成绩进行排序,并显示排名(实现不完全)

– mysql没有rank函数
–方法1
-- 关于排名的sql,很蛋疼的是可能会涉及到不同的同分情况下,是否占用排名的形式
-- 在select的项里面,可以使用查找语句,查找出的是一个值就是了

(SELECT * FROM
(SELECT s1.s_id, s1.c_id, s1.s_score,
(SELECT COUNT(distinct sc.s_score) FROM score sc
WHERE sc.s_score>=s1.s_score AND sc.c_id = '01') as 'rank不保留排名'
FROM score s1 WHERE s1.c_id = '01' ORDER BY s1.s_score DESC) t1)
UNION (SELECT * FROM
(SELECT s1.s_id, s1.c_id, s1.s_score,
(SELECT COUNT(DISTINCT sc.s_score) FROM score sc
WHERE sc.s_score>=s1.s_score AND sc.c_id = '02') 'rank不保留排名'
FROM score s1 WHERE s1.c_id = '02' ORDER BY s1.s_score DESC) t2)
UNION (SELECT * FROM
(SELECT s1.s_id, s1.c_id, s1.s_score,
(SELECT COUNT(DISTINCT sc.s_score) FROM score sc
WHERE sc.s_score>=s1.s_score AND sc.c_id = '03') 'rank不保留排名'
FROM score s1 WHERE s1.c_id = '03' ORDER BY s1.s_score DESC) t3)

–方法2

(SELECT a.s_id, a.c_id, @i:=@i+1 AS i保留排名,
@k:=(CASE WHEN @score = a.s_score THEN @k ELSE @i END) AS rank不保留排名,
@score:=a.s_score AS score
FROM (SELECT * FROM score WHERE c_id = '01' GROUP BY s_id, c_id, s_score ORDER BY s_score DESC)a,
(SELECT @i:=0, @k:=0, @score:=0)b)
UNION
(SELECT a.s_id, a.c_id, @m:=@m+1 AS i保留排名,
@k:=(CASE WHEN @score = a.s_score THEN @k ELSE @m END) AS rank不保留排名,
@score:=a.s_score AS score
FROM (SELECT * FROM score WHERE c_id = '02' GROUP BY s_id, c_id, s_score ORDER BY s_score DESC)a,
(SELECT @m:=0, @k:=0, @score:=0)b)
UNION
(SELECT a.s_id, a.c_id, @x:=@x+1 AS i保留排名,
@k:=(CASE WHEN @score = a.s_score THEN @k ELSE @x END) AS rank不保留排名,
@score:=a.s_score AS score
FROM (SELECT * FROM score WHERE c_id = '03' GROUP BY s_id, c_id, s_score ORDER BY s_score DESC)a,
(SELECT @x:=0, @k:=0, @score:=0)b);

# 查询学生的总成绩并进行排名

SELECT score.s_id, s_name, sum(s_score) sumscore
FROM score,
student
WHERE score.s_id = student.s_id
GROUP BY score.s_id
ORDER BY sumscore DESC;

# 查询不同老师所教不同课程平均分从高到低显示

–方法1
-- 自行写法,参考写法实在是多此一举啊
SELECT t.t_id,sc.c_id,t.t_name,avg(sc.s_score) avgScore
FROM teacher t INNER JOIN course c ON t.t_id = c.t_id
INNER JOIN score sc ON sc.c_id = c.c_id
GROUP BY t.t_id,sc.c_id ORDER BY avgScore DESC ;

SELECT tmp.c_id, t_id, avgscore AS '平均分'
FROM ((SELECT DISTINCT c_id, (round((SELECT avg(s_score) FROM score WHERE c_id = '01' GROUP BY c_id), 2))avgscore
FROM score s1
WHERE c_id = '01')
UNION
(SELECT DISTINCT c_id, (round((SELECT avg(s_score) FROM score WHERE c_id = '02' GROUP BY c_id), 2))avgscore
FROM score s1
WHERE c_id = '02')
UNION
(SELECT DISTINCT c_id, (round((SELECT avg(s_score) FROM score WHERE c_id = '03' GROUP BY c_id), 2))avgscore
FROM score s1
WHERE c_id = '03'))tmp,
course
WHERE tmp.c_id = course.c_id
ORDER BY tmp.avgscore DESC;

–方法2

SELECT course.c_id, course.t_id, t_name, round(avg(s_score), 2)AS avgscore
FROM course
JOIN teacher ON teacher.t_id = course.t_id
JOIN score ON course.c_id = score.c_id
GROUP BY score.c_id
ORDER BY avgscore DESC;

–方法3
-- 使用cross join 的方式反而是对查询效率的降级
SELECT course.c_id, course.t_id, t_name, round(avg(s_score), 2)AS avgscore
FROM course,
teacher,
score
WHERE teacher.t_id = course.t_id
AND course.c_id = score.c_id
GROUP BY score.c_id
ORDER BY avgscore DESC;

# 查询所有课程的成绩第2名到第3名的学生信息及该课程成绩

–方法1
-- 由于这种情况下,group by 之后没有办法使用limit,而这种特定的名词就是使用Limit的处理合适,所以就使用union进行连接

(SELECT student., tmp1.c_id, tmp1.s_score FROM student,
(SELECT s_id, c_id, s_score FROM score WHERE c_id = '01' ORDER BY s_score DESC LIMIT 1, 2)tmp1
WHERE student.s_id = tmp1.s_id)
UNION (SELECT student.
, tmp2.c_id, tmp2.s_score FROM student,
(SELECT s_id, c_id, s_score FROM score WHERE c_id = '02' ORDER BY s_score DESC LIMIT 1, 2)tmp2
WHERE student.s_id = tmp2.s_id)
UNION (SELECT student.*, tmp3.c_id, tmp3.s_score FROM student,
(SELECT s_id, c_id, s_score FROM score WHERE c_id = '03' ORDER BY s_score DESC LIMIT 1, 2)tmp3
WHERE student.s_id = tmp3.s_id);

–方法2
-- 直接找出排名,然后对排名进行筛选,当然是一种方法,但是并不推荐
(SELECT student., tmp.c_id, tmp.s_score, tmp.排名 FROM (
SELECT a.s_id, a.c_id, a.s_score, @i:=@i+1 AS 排名 FROM score a, (SELECT @i:=0)b
WHERE a.c_id = '01' ORDER BY a.s_score DESC
)tmp JOIN student ON tmp.s_id = student.s_id WHERE 排名 BETWEEN 2 AND 3)
UNION (
SELECT student.
, tmp.c_id, tmp.s_score, tmp.排名 FROM (
SELECT a.s_id, a.c_id, a.s_score, @j:=@j+1 AS 排名 FROM score a, (SELECT @j:=0)b
WHERE a.c_id = '02' ORDER BY a.s_score DESC
)tmp JOIN student ON tmp.s_id = student.s_id WHERE 排名 BETWEEN 2 AND 3
) UNION (
SELECT student.*, tmp.c_id, tmp.s_score, tmp.排名 FROM (
SELECT a.s_id, a.c_id, a.s_score, @k:=@k+1 AS 排名 FROM score a, (SELECT @k:=0)b
WHERE a.c_id = '03' ORDER BY a.s_score DESC
)tmp JOIN student ON tmp.s_id = student.s_id WHERE 排名 BETWEEN 2 AND 3);

# 统计各科成绩各分数段人数:课程编号,课程名称,100-85,85-70,70-60,0-60及所占百分比

-- 很简单可以搞定的东西,为何需要那么复杂啊。。
select c.c_id,c.c_name,
sum(sc.s_score<=100 AND sc.s_score>=85) AS a,
sum(sc.s_score<85 AND sc.s_score>=70) AS b,
sum(sc.s_score<70 AND sc.s_score>=60) AS c
FROM course c INNER JOIN score sc ON c.c_id = sc.c_id
GROUP BY c.c_id ;

# 查询学生平均成绩及其名次

  • 因为MySQL没有rowcount的函数,所以需要使用此种形式

SELECT a.s_id, a.s_name, a.平均分, @i := @i + 1 AS 排名
FROM (SELECT student.s_id, student.s_name, avg(score.s_score) AS "平均分"
FROM student,
score
WHERE student.s_id = score.s_id
GROUP BY score.s_id
ORDER BY 平均分 DESC)a,
(SELECT @i := 0)b;

# 查询各科成绩前三名的记录

– 1.选出b表比a表成绩大的所有组
– 2.选出比当前id成绩大的 小于三个的
–没有查学生姓名

  • 查找前几名的方法,使用find_in_set真的是可以事半功倍啊!!
    SELECT s1.*,s2.c_name FROM score s1 INNER JOIN
    (SELECT sc.c_id,c.c_name,group_concat(sc.s_id ORDER BY sc.s_score DESC) as sids
    FROM score sc INNER JOIN course c on c.c_id = sc.c_id GROUP BY sc.c_id) s2 ON s1.c_id = s2.c_id WHERE
    find_in_set(s1.s_id,s2.sids) BETWEEN 1 AND 3 ORDER BY s1.c_id,s1.s_score DESC ;

(SELECT score.c_id, course.c_name, s_score FROM score, course
WHERE score.c_id = '01' AND course.c_id = score.c_id ORDER BY s_score DESC LIMIT 3)
UNION
(SELECT score.c_id, course.c_name, s_score FROM score, course
WHERE score.c_id = '02' AND course.c_id = score.c_id ORDER BY s_score DESC LIMIT 3)
UNION
(SELECT score.c_id, course.c_name, s_score FROM score, course
WHERE score.c_id = '03' AND course.c_id = score.c_id ORDER BY s_score DESC LIMIT 3);

–查了学生姓名

(SELECT score.c_id, course.c_name, student.s_name, s_score FROM score
JOIN student ON student.s_id = score.s_id
JOIN course ON score.c_id = '01' AND course.c_id = score.c_id ORDER BY s_score DESC LIMIT 3)
UNION (
SELECT score.c_id, course.c_name, student.s_name, s_score FROM score
JOIN student ON student.s_id = score.s_id
JOIN course ON score.c_id = '02' AND course.c_id = score.c_id ORDER BY s_score DESC LIMIT 3

) UNION (
SELECT score.c_id, course.c_name, student.s_name, s_score FROM score
JOIN student ON student.s_id = score.s_id
JOIN course ON score.c_id = '03' AND course.c_id = score.c_id ORDER BY s_score DESC LIMIT 3);

# 查询每门课程被重修的学生数

  • 能直接连接就不要使用子查询,使用count(1)的形式其实是不严谨的
    SELECT c.c_id,c.c_name,count(DISTINCT sc.s_id) AS cnt FROM course c LEFT JOIN score sc ON c.c_id = sc.c_id
    WHERE sc.s_score < 60
    GROUP BY c.c_id;

SELECT c.c_id, c.c_name, a.被选修人数
FROM course c
JOIN (SELECT c_id, count(1) AS 被选修人数 FROM score WHERE score.s_score < 60 GROUP BY score.c_id)a
ON a.c_id = c.c_id;

# 查询出只有两门课程的全部学生的学号和姓名

  • 还是那句话,如果已经group by了完全的s_id了,那么其他的项都是可以获取到的
    SELECT s.s_id,s.s_name
    FROM student s INNER JOIN score sc ON s.s_id = sc.s_id GROUP BY s.s_id HAVING count(DISTINCT c_id) = 2;

SELECT st.s_id, st.s_name
FROM student st
JOIN (SELECT s_id FROM score GROUP BY s_id HAVING count(c_id) = 2)a ON st.s_id = a.s_id;

# 查询男生、女生人数

SELECT
sum(s_sex = '男') as male,
sum(s_sex = '女') as female
FROM student;

SELECT a.男生人数, b.女生人数
FROM (SELECT count(1) AS 男生人数 FROM student WHERE s_sex = '男')a,
(SELECT count(1) AS 女生人数 FROM student WHERE s_sex = '女')b;

# 查询名字中含有"风"字的学生信息

SELECT *
FROM student
WHERE s_name LIKE '%风%';

# 查询同名同性学生名单,并统计同名人数

  • 统计个数就是聚合的方式,很简单,直接group by就是了,大不了再用find_in_set就是了
    SELECT s_name,s_sex,GROUP_CONCAT(s_id) sids,count(s_id) cnt
    FROM student GROUP BY s_name,s_sex HAVING count(s_id) >=2;

  • 这是错误的写法,老哥啊
    SELECT s1.s_name, s1.s_sex, count(*) AS 同名人数
    FROM student s1,
    student s2
    WHERE s1.s_name = s2.s_name
    AND s1.s_id <> s2.s_id
    AND s1.s_sex = s2.s_sex
    GROUP BY s1.s_name, s1.s_sex;

# 查询1990年出生的学生名单

SELECT *
FROM student
WHERE s_birth LIKE '1990%';

# 查询每门课程的平均成绩,结果按平均成绩降序排列,平均成绩相同时,按课程编号升序排列

SELECT score.c_id, c_name, round(avg(s_score), 2) AS 平均成绩
FROM score
JOIN course ON score.c_id = course.c_id
GROUP BY c_id
ORDER BY 平均成绩 DESC, score.c_id ASC;

# 查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩

SELECT s.s_id,s.s_name,round(avg(sc.s_score),2) AS avgScore
FROM student s INNER JOIN score sc ON s.s_id = sc.s_id
GROUP BY s.s_id HAVING avgScore >= 85;

SELECT score.s_id, s_name, round(avg(s_score), 2)AS 平均成绩
FROM score
JOIN student ON student.s_id = score.s_id
GROUP BY score.s_id
HAVING 平均成绩 >= 85;

# 查询课程名称为"数学",且分数低于60的学生姓名和分数

SELECT s_name, s_score AS 数学成绩
FROM student
JOIN (SELECT s_id, s_score
FROM score,
course
WHERE score.c_id = course.c_id
AND c_name = '数学')a ON a.s_score < 60 AND student.s_id = a.s_id;

# 查询所有学生的课程及分数情况

  • 相当于行列转换的用法了,由于需要就算总分,必须要要使用聚合
    SELECT a.s_name,
    SUM(CASE c.c_name WHEN '语文' THEN b.s_score ELSE 0 END) AS 语文,
    SUM(CASE c.c_name WHEN '数学' THEN b.s_score ELSE 0 END) AS 数学,
    SUM(CASE c.c_name WHEN '英语' THEN b.s_score ELSE 0 END) AS 英语,
    SUM(b.s_score) AS 总分
    FROM student a
    JOIN score b ON a.s_id = b.s_id
    JOIN course c ON b.c_id = c.c_id
    GROUP BY s_name, a.s_id;

# 查询任何一门课程成绩在70分以上的学生姓名、课程名称和分数

SELECT s.s_id,s.s_name,sc.s_score FROM student s INNER JOIN score sc ON s.s_id = sc.s_id
WHERE sc.s_id not IN
(SELECT s_id FROM score WHERE s_score < 70 GROUP BY s_id);

  • 又是一个错误的写法
    SELECT s_name, c_name, s_score
    FROM score
    JOIN student ON student.s_id = score.s_id
    JOIN course ON score.c_id = course.c_id
    WHERE s_score < 70;

# 查询不及格的课程

SELECT s_name, c_name AS 不及格课程, tmp.s_score
FROM student
JOIN (SELECT s_id, s_score, c_name
FROM score,
course
WHERE score.c_id = course.c_id
AND s_score < 60)tmp ON student.s_id = tmp.s_id;

# 查询课程编号为01且课程成绩在80分以上的学生的学号和姓名

SELECT student.s_id, s_name, s_score AS score_01
FROM student
JOIN score ON student.s_id = score.s_id
WHERE c_id = '01'
AND s_score >= 80;

# 求每门课程的学生人数

SELECT course.c_id, course.c_name, count(1)AS 选课人数
FROM course
JOIN score ON course.c_id = score.c_id
GROUP BY score.c_id;

# 查询选修"张三"老师所授课程的学生中,成绩最高的学生信息及其成绩

– 查询老师id

  • 此种查法会丢失调同样都是最高分的学生
    SELECT s.*,c.c_name,sc.s_score
    FROM student s INNER JOIN score sc ON s.s_id = sc.s_id
    INNER join course c ON sc.c_id = c.c_id
    INNER JOIN teacher t ON c.t_id = t.t_id
    WHERE t.t_name= '张三' ORDER BY sc.s_score DESC LIMIT 1;

select s.*,sc.s_score FROM student s inner join score sc ON s.s_id = sc.s_id
where sc.s_score = (
SELECT max(sc.s_score)
FROM score sc INNER join course c ON sc.c_id = c.c_id
INNER JOIN teacher t ON c.t_id = t.t_id
WHERE t.t_name= '张三'
);

– 查询最高分(可能有相同分数)

SELECT max(s_score)
FROM score
JOIN (SELECT course.c_id, c_name
FROM course,
(SELECT t_id, t_name FROM teacher WHERE t_name = '张三')tmp
WHERE course.t_id = tmp.t_id)tmp2 ON score.c_id = tmp2.c_id;

# 查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

SELECT DISTINCT a.s_id, a.c_id, a.s_score
FROM score a,
score b
WHERE a.c_id <> b.c_id
AND a.s_score = b.s_score;

# 查询每门课程成绩最好的前两名

–方法1(该方法有bug, 不能查出临界的重复值, 例如查各科的第一名或前三名)

  • 这里如果第一名的话,显然就有问题了
    SELECT a.s_id, a.c_id, a.s_score
    FROM score a
    WHERE (SELECT count(1)
    FROM score b
    WHERE a.c_id = b.c_id
    AND b.s_score >= a.s_score) <= 2
    ORDER BY a.c_id ASC, a.s_score DESC;

–方法2(查前三名)

  • 达成这种效果的话,其实find_in_set的方式更加合理和擅长
    (SELECT * FROM score WHERE c_id = '01' ORDER BY s_score DESC LIMIT 3)
    UNION (
    SELECT * FROM score WHERE c_id = '02' ORDER BY s_score DESC LIMIT 3)
    UNION (
    SELECT * FROM score WHERE c_id = '03' ORDER BY s_score DESC LIMIT 3);

-方法三

  • 仍然是使用find_in_set的方式,比起其他的真是好用很多了
    SELECT sc.* FROM score sc INNER JOIN
    (SELECT c_id,group_concat(s_id ORDER by s_score DESC) sids
    FROM score GROUP BY c_id) tmp ON sc.c_id = tmp.c_id WHERE
    find_in_set(sc.s_id,tmp.sids) BETWEEN 1 AND 2 ORDER BY sc.c_id,s_score DESC ;

# 统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

SELECT DISTINCT course.c_id, tmp.选修人数
FROM course
JOIN (SELECT c_id, count(1) AS 选修人数 FROM score GROUP BY c_id)tmp
WHERE tmp.选修人数 >= 5
ORDER BY tmp.选修人数 DESC, course.c_id ASC;

# 检索至少选修两门课程的学生学号

SELECT s_id, count(c_id) AS totalCourse
FROM score
GROUP BY s_id
HAVING count(c_id) >= 2;

# 查询选修了全部课程的学生信息

SELECT student.*
FROM student,
(SELECT s_id, count(c_id) AS totalCourse FROM score GROUP BY s_id)tmp
WHERE student.s_id = tmp.s_id
AND totalCourse = 3;

# 查询各学生的年龄

– 按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一

  • date_format之后的可以直接进行加减运算,这个就算是记下了
    SELECT s_name, s_birth, (DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(s_birth, '%Y') -
    CASE
    WHEN (DATE_FORMAT(NOW(), '%m%d') > DATE_FORMAT(s_birth, '%m%d')) THEN 1
    ELSE 0 END) AS age
    FROM student;

# 查询本周过生日的学生

–方法1
SELECT *,week(s_birth) FROM student
WHERE week(now()) = week(concat(date_format(now(),'%Y'),date_format(s_birth,'%m%d')));

  • 以下全错啊!!
    SELECT *
    FROM student
    WHERE WEEK(DATE_FORMAT(NOW(), '%Y%m%d')) = WEEK(s_birth);

# 查询本月过生日的学生

–方法1

SELECT *,month(s_birth)
FROM student
WHERE MONTH(DATE_FORMAT(NOW(), '%Y%m%d')) = MONTH(s_birth);
–方法2

  • 这种方法很不正规
    SELECT s_name, s_sex, s_birth
    FROM student
    WHERE substring(s_birth, 6, 2) = '03';
最后编辑时间: 12/24/2020, 3:33:40 PM