• SQL语法学习记录(三)


    牛客-SQL进阶挑战 里的题目,这里只记录1~25题

    除了之前的查询,还包括创建表,创建索引等

    -- 1. 插入数据
    INSERT INTO exam_record (uid, exam_id, start_time, submit_time, score)
    values (1001, 9001, "2021-09-01 22:11:12", "2021-09-01 23:01:12", 90),
            (1002, 9002, "2021-09-04 07:01:02", null, null)
    
    
    -- 省略列名,默认使用所有的列
    -- 自增Id 填充null/default/0
    INSERT INTO exam_record
    values (null, 1001, 9001, "2021-09-01 22:11:12", "2021-09-01 23:01:12", 90),
            (null, 1002, 9002, "2021-09-04 07:01:02", null, null)
    
    -- 2. 插入,从另一张表中导入数据
    -- 自增主键不要复制
    INSERT INTO exam_record_before_2021(uid, exam_id, start_time, submit_time, score)
    SELECT uid, exam_id, start_time, submit_time, score
    FROM exam_record
    WHERE submit_time like '2020%'
    
    -- 填充0或null,不能用default
    INSERT INTO exam_record_before_2021
    SELECT null, uid, exam_id, start_time, submit_time, score
    FROM exam_record
    WHERE submit_time like '2020%'
    
    
    -- 3. repalce into
    -- 插入数据的表必须有主键或者是唯一索引!否则的话,replace into 会直接插入数据,这将导致表中出现重复的数据。
    REPLACE INTO examination_info 
    values (null, 9003, "SQL", "hard", 90, "2021-01-01 00:00:00")
    
    -- 7. delete + limit
    DELETE FROM exam_record
    WHERE submit_time is null or timestampdiff(minute, start_time, submit_time)<5
    ORDER BY start_time
    LIMIT 3
    
    -- 8. 删除表
    -- DROP TABLE 清除数据并且销毁表
    -- TRUNCATE TABLE 只清除数据,保留表结构,列,权限,索引,视图,关
    -- DELETE TABLE 删除(符合某些条件的)数据,执行后可以撤销
    truncate exam_record
    
    -- 9. 创建表
    -- PRIMARY KEY -- 可选的约束,主键
    -- FOREIGN KEY -- 外键,引用其他表的键值
    -- AUTO_INCREMENT -- 自增ID
    -- COMMENT comment -- 列注释(评论)
    -- DEFAULT default_value -- 默认值
    -- UNIQUE -- 唯一性约束,不允许两条记录该列值相同
    -- NOT NULL -- 该列非空
    
    CREATE TABLE IF NOT EXISTS user_info_vip(
        id int(11)  primary key auto_increment comment '自增ID',
        uid int(11) unique  not null comment '用户ID',
        nick_name varchar(64)	comment '昵称',
        achievement int(11) default 0 comment '成就值',
        level int(11) comment '用户等级',
        job varchar(32) comment '职业方向',
        register_time datetime default CURRENT_TIMESTAMP comment '注册时间'
    )
    
    
    -- 10. 修改表
    ALTER TABLE user_info add school varchar(15) after level;
    ALTER TABLE user_info change job profession varchar(10);
    ALTER TABLE user_info modify achievement int(11) default 0;
    
    -- 11. 删除多张表
    drop table if EXISTS exam_record_2011, exam_record_2012, exam_record_2013, exam_record_2014;
    
    -- 12. 创建索引
    -- 普通索引、唯一索引、全文索引
    CREATE INDEX idx_duration ON examination_info(duration);
    CREATE UNIQUE INDEX uniq_idx_exam_id ON examination_info(exam_id);
    CREATE FULLTEXT INDEX full_idx_tag ON examination_info(tag);
    
    -- 13. 删除索引
    -- 好像不能用delete, 也不能一起删除
    DROP INDEX uniq_idx_exam_id ON examination_info;
    DROP INDEX full_idx_tag ON examination_info;
    
    -- 14. 截断平均值
    -- sum-min-max
    SELECT tag, difficulty, 
            round((sum(score)-min(score)-max(score))/(count(score)-2), 1) as clip_avg_score
    FROM examination_info
    LEFT JOIN exam_record using(exam_id)
    WHERE tag="SQL" and difficulty="hard"
    GROUP BY tag
    
    -- 15. distinct
    -- + if
    SELECT count(start_time) as total_pv,
            count(submit_time) as complete_pv,
            count(distinct if(score is null, null, exam_id)) as complete_exam_cnt
    FROM exam_record
    
    
    -- + case
    SELECT count(start_time) as total_pv,
            count(submit_time) as complete_pv,
            count(distinct case when score is null then null else exam_id end) as complete_exam_cnt
    FROM exam_record
    
    -- 16. 得分不小于平均分的最小值
    -- where 子句 >
    SELECT min(score) as min_score_over_avg
    FROM exam_record a
    LEFT JOIN examination_info b using(exam_id)
    WHERE b.tag = "SQL" and score>=(
        SELECT avg(score) as avg_score
        FROM exam_record a
        LEFT JOIN examination_info b using(exam_id)
        WHERE tag = "SQL"
    )
    
    -- 聚合窗口函数 avgSELECT min(score) as min_score_over_avg
    FROM (
        SELECT score, avg(score) over(partition by tag) as avg_score
        FROM exam_record a
        LEFT JOIN examination_info b using(exam_id)
        WHERE tag = "SQL"
    ) t
    WHERE score>=avg_score
    
    
    
    SELECT month, count(score) as avg_active_days, count(distinct uid) as mau
    FROM (
        SELECT month(submit_time) as month, score, uid
        FROM exam_record
    ) a
    GROUP BY month
    
    -- 17. 平均活跃天数和月活人数
    -- 注意 同一个人一天活跃多次的情况, 只算一次, 因此要用distinct uid, day
    -- 1)不行
    SELECT month, round(count(distinct uid)/count(distinct uid), 2) as avg_active_days, count(distinct uid) as mau
    # SELECT *
    FROM (
        SELECT date_format(submit_time, "%Y%m") as month, submit_time, score, uid
        FROM exam_record
        WHERE submit_time is not null and year(submit_time)=2021
    ) a
    GROUP BY month
    
    -- 2)行
    SELECT month, round(count(distinct uid, day)/count(distinct uid), 2) as avg_active_days, count(distinct uid) as mau
    # SELECT *
    FROM (
        SELECT date_format(submit_time, "%Y%m") as month, date_format(submit_time, "%Y%m%d") as day, submit_time, score, uid
        FROM exam_record
        WHERE submit_time is not null and year(submit_time)=2021
    ) a
    GROUP BY month
    
    -- 18. 计算月平均
    -- max(day(last_day(submit_time)))  一个月的天数
    SELECT date_format(submit_time, '%Y%m') as submit_month,
            count(question_id) as month_q_cnt, 
            round(count(question_id) / max(day(last_day(submit_time))), 3) as avg_day_q_cnt
    FROM practice_record
    WHERE year(submit_time) = 2021
    GROUP BY submit_month
    
    
    UNION
    
    SELECT concat(date_format(submit_time, '%Y'), "汇总") as submit_month, 
            count( question_id) as month_q_cnt, 
            round(count( question_id)/31, 3) as avg_day_q_cnt
    FROM practice_record
    WHERE year(submit_time) = 2021
    GROUP BY submit_month
    
    ORDER BY submit_month
    
    
    -- 19. group_concat
    -- group_concat([distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator '分隔符'])
    -- 这里需要dictinct, 因为对于同一个uid,day+tag 可能有多个记录,例如tag="SQL",day="2019-01-01", 但是有"Easy" 和 "Herd" 两个版本
    SELECT  uid, 
            count(start_time)-count(submit_time) as incomplete_cnt,
            count(submit_time) as complete_cnt,
            group_concat(distinct concat(date_format(start_time, "%Y-%m-%d"), ':', tag) separator ';') as detail
    FROM exam_record as a
    LEFT JOIN examination_info as b using(exam_id)
    WHERE year(start_time)=2021
    GROUP BY uid
    HAVING complete_cnt>=1 and incomplete_cnt>1 and incomplete_cnt<5
    ORDER BY incomplete_cnt desc
    
    
    -- 20. 在月平均满足条件下,统计tag
    -- 计算月平均 HAVING count(date_format(submit_time, "%Y%m")) / count(distinct date_format(submit_time, "%Y%m")) >=3
    SELECT tag, count(*) as tag_cnt
    FROM exam_record
    LEFT JOIN examination_info using(exam_id)
    WHERE uid in (
        SELECT uid
        FROM exam_record
        GROUP BY uid
        HAVING count(date_format(submit_time, "%Y%m")) / count(distinct date_format(submit_time, "%Y%m")) >=3
    ) 
    GROUP BY tag
    ORDER BY tag_cnt desc
    
    
    -- 21.考试记录+考试信息+用户信息
    -- 三表联合查询
    SELECT exam_id, count(distinct uid) as uv, round(avg(score), 1) as avg_score
    FROM exam_record
    LEFT JOIN user_info using(uid)
    LEFT JOIN examination_info using(exam_id)
    WHERE tag='SQL' and level>5
    GROUP BY exam_id
    ORDER BY uv desc, avg_score
    
    -- 22. 和上一题类似
    SELECT level, count(*) as level_cnt
    FROM exam_record
    LEFT JOIN user_info using(uid)
    LEFT JOIN examination_info using(exam_id)
    WHERE tag="SQL" and score>80
    GROUP BY level
    ORDER BY level_cnt desc
    
    -- 23. union 要分别排序
    -- union可以使用任何selcet语句,但order by子句只能在最后一次使用
    -- 所以为了分开排序,就再套了一个select语句
    SELECT * FROM (
        SELECT exam_id as tid, count(distinct uid) as uv, count(*) as pv
        FROM exam_record
        GROUP BY exam_id
        ORDER BY uv desc, pv desc
    ) a
    
    UNION ALL
    
    SELECT * FROM (
        SELECT question_id as tid, count(distinct uid) as uv, count(*) as pv
        FROM practice_record
        GROUP BY question_id
        ORDER BY uv desc, pv desc
    ) b
    
    -- 24. 两种类别,用union
    -- 注意顺序问题,where, group by, order by
    SELECT uid, "activity1" as activity
    FROM exam_record
    LEFT JOIN examination_info using(exam_id)
    WHERE year(start_time)=2021
    GROUP BY uid
    HAVING min(score)>=85
    
    UNION 
    
    SELECT uid, "activity2" as activity
    FROM exam_record
    LEFT JOIN examination_info using(exam_id)
    WHERE timestampdiff(second, start_time, submit_time) <= (duration*60)/2 
            and score>80 
            and difficulty="hard"
            and year(start_time)=2021
    ORDER BY uid
    
    
    -- 25. 不亏为困难题
    -- 关键,先查出符合条件的uid,再与practice_record联合
    SELECT uid, exam_cnt, count(question_id) as question_cnt
    FROM (
        SELECT uid, count(score) as exam_cnt
        FROM exam_record
        WHERE uid in (
            SELECT uid
            FROM exam_record
            LEFT JOIN examination_info using(exam_id)
            LEFT JOIN user_info using(uid)
            WHERE tag="SQL" and difficulty="hard" and level=7
            GROUP BY uid
            HAVING avg(score)>80
        ) and year(submit_time)=2021
        GROUP BY uid
        HAVING count(score)>=1
    ) a
    LEFT JOIN practice_record b using(uid)
    WHERE year(submit_time)=2021 or submit_time is null  # 未做题不能去掉,应为0
    GROUP BY uid
    ORDER BY exam_cnt, question_cnt desc
    
  • 相关阅读:
    js面试相关
    邮件(一):Springboot+thymeleaf的发邮件部分
    饿了么组件--table组件自定义渲染列,同时伴有v-for和v-if情况
    java开发规范学习
    java发送邮件
    vue垂死挣扎--遇到的问题
    vue学习记录
    matlab---设置背景颜色为白色
    Git push时不需要总输入密码
    我不知道的js(一)作用域与闭包
  • 原文地址:https://www.cnblogs.com/lfri/p/16210590.html
Copyright © 2020-2023  润新知