zoukankan      html  css  js  c++  java
  • Django学习之ORM练习题

    一.表关系

    创建表关系,并创建约束

    班级表:class

    学生表:

    student

    cid

    caption

    grade_id

    sid

    sname

    gender

    class_id

    1

    一年一班

    1

    1

    乔丹

    1

    2

    二年一班

    2

    2

    艾弗森

    1

    3

    三年二班

    3

    3

    科比

    2

    老师表:teacher

    课程表:

    course

    tid

    tname

    cid

    cname

    teacher_id

    1

    张三

    1

    生物

    1

    2

    李四

    2

    体育

    1

    3

    王五

    3

    物理

    2

    成绩表:score

    年级表:

    class_grade

    sid

    student_id

    course_id

    score

    gid

    gname

    1

    1

    1

    60

    1

    一年级

    2

    1

    2

    59

    2

    二年级

    3

    2

    2

    99

    3

    三年级

    班级任职表:

    teach2cls

    tcid

    tid

    cid

    1

    1

    1

    2

    1

    2

    3

    2

    1

    4

    3

    2

     

    .创建测试数据

    1.创建项目准备环境

    步骤:

    (1)在终端使用mkvirtualenv命令创建一个新的虚拟环境,然后使用pip3命令下载安装django

    mkvirtualenv ORMtest -p python3

    pip3 install django

    (2)使用django-admin命令创建django项目

    django-admin startproject ORMtest

    (3)pycharm打开该项目,配置python编译器

    (4)pycharm的终端使用startapp新建子应用

    python3 manage.py startapp SMS

    (5)在配置文件settings.py中注册新建的子应用SMS

    # Application definition

    INSTALLED_APPS = [

        'django.contrib.admin',

        'django.contrib.auth',

        'django.contrib.contenttypes',

        'django.contrib.sessions',

        'django.contrib.messages',

        'django.contrib.staticfiles',

        'SMS.apps.SmsConfig',  # <---注册新应用

    ]

    2.创建模型

    步骤:

    (1)在子应用SMS文件内的模型文件models.py中创建模型类

    from django.db import models
    
    # Create your models here.
    class Classes(models.Model):
        cid = models.AutoField(primary_key=True)
        caption = models.CharField(max_length=32)
        grade = models.ForeignKey("ClassGrade", on_delete=models.CASCADE)
    
    
    class ClassGrade(models.Model):
        gid = models.AutoField(primary_key=True)
        gname = models.CharField(max_length=32)
    
    
    class Student(models.Model):
        sid = models.AutoField(primary_key=True)
        sname = models.CharField(max_length=32)
        gender_choice = ((0, ""), (1, ""))
        gender = models.SmallIntegerField(choices=gender_choice, default=1)
        classes = models.ForeignKey("Classes", on_delete=models.CASCADE)
    
    
    class Teacher(models.Model):
        tid = models.AutoField(primary_key=True)
        tname = models.CharField(max_length=32)
        classes = models.ManyToManyField("Classes")
    
    
    class Course(models.Model):
        cid = models.AutoField(primary_key=True)
        cname = models.CharField(max_length=32)
        teacher = models.ForeignKey("Teacher", on_delete=models.CASCADE)
    
    
    class Score(models.Model):
        sid = models.AutoField(primary_key=True)
        student = models.ForeignKey("Student", on_delete=models.CASCADE)
        course = models.ForeignKey('Course', on_delete=models.CASCADE)
        score = models.IntegerField()
    models.

    (2)执行数据库迁移命令

    python3 manage.py makemigrations
    python3 manage.py migrate

    3.添加数据

    (1)班级表

    INSERT INTO SMS_classes (cid, caption, grade_id) VALUES (1, '一年1班', 1);
    INSERT INTO SMS_classes (cid, caption, grade_id) VALUES (2, '一年2班', 1);
    INSERT INTO SMS_classes (cid, caption, grade_id) VALUES (3, '二年1班', 2);
    INSERT INTO SMS_classes (cid, caption, grade_id) VALUES (4, '二年2班', 2);
    INSERT INTO SMS_classes (cid, caption, grade_id) VALUES (5, '三年1班', 3);
    INSERT INTO SMS_classes (cid, caption, grade_id) VALUES (6, '三年2班', 3);
    INSERT INTO SMS_classes (cid, caption, grade_id) VALUES (7, '三年3班', 3);
    INSERT INTO SMS_classes (cid, caption, grade_id) VALUES (8, '四年1班', 4);

    (2)年级表

    INSERT INTO SMS_classgrade (gid, gname) VALUES (1, '一年级');
    INSERT INTO SMS_classgrade (gid, gname) VALUES (2, '二年级');
    INSERT INTO SMS_classgrade (gid, gname) VALUES (3, '三年级');
    INSERT INTO SMS_classgrade (gid, gname) VALUES (4, '四年级');

    (3)学生表

    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (1, '张无忌', 2, 1);
    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (2, '赵敏', 1, 0);
    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (3, '令狐冲', 3, 1);
    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (4, '任盈盈', 4, 0);
    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (5, '方世玉', 5, 1);
    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (6, '张飞', 6, 1);
    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (7, '武松', 8, 1);
    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (8, '鲁智深', 7, 1);
    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (9, '金莲', 6, 0);
    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (10, '西门庆', 8, 1);
    INSERT INTO SMS_student (sid, sname, classes_id, gender) VALUES (11, '林冲', 7, 1);

    (4)教师表

    INSERT INTO SMS_teacher (tid, tname) VALUES (1, '乔峰');
    INSERT INTO SMS_teacher (tid, tname) VALUES (2, '任盈盈');
    INSERT INTO SMS_teacher (tid, tname) VALUES (3, '任我行');
    INSERT INTO SMS_teacher (tid, tname) VALUES (4, '岳不群');
    INSERT INTO SMS_teacher (tid, tname) VALUES (5, '唐僧');

    (5)课程表

    INSERT INTO SMS_course (cid, cname, teacher_id) VALUES (1, '物理', 3);
    INSERT INTO SMS_course (cid, cname, teacher_id) VALUES (2, '生物', 1);
    INSERT INTO SMS_course (cid, cname, teacher_id) VALUES (3, '语文', 5);
    INSERT INTO SMS_course (cid, cname, teacher_id) VALUES (4, '数学', 4);
    INSERT INTO SMS_course (cid, cname, teacher_id) VALUES (5, '日语', 1);
    INSERT INTO SMS_course (cid, cname, teacher_id) VALUES (6, '体育', 2);

    (6)成绩表

    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (1, 80, 1, 2);
    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (2, 60, 1, 3);
    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (3, 72, 2, 1);
    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (4, 58, 3, 1);
    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (5, 91, 4, 5);
    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (6, 84, 5, 5);
    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (7, 78, 6, 8);
    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (8, 82, 4, 7);
    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (9, 87, 4, 6);
    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (10, 57, 2, 3);
    INSERT INTO SMS_score (sid, score, course_id, student_id) VALUES (11, 68, 3, 2);
    insert into SMS_score (sid, score, course_id, student_id) values (12, 73, 2, 2);

    (7)班级任职表

    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (1, 1, 8);
    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (2, 1, 7);
    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (3, 1, 6);
    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (4, 2, 5);
    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (5, 3, 4);
    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (6, 3, 5);
    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (7, 4, 4);
    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (8, 5, 3);
    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (9, 2, 2);
    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (10, 3, 1);
    INSERT INTO SMS_teacher_classes (id, teacher_id, classes_id) VALUES (11, 4, 1);

    三.习题与答案解析

    1.查询学生总人数;

    思路:直接查,然后用聚合函数Count计算学生个数

    SQL:

        select count(sid) from student

    Python:

        res = Student.objects.all().count()

        res = Student.objects.aggregate(Count('sid'))

     

    2.查询生物课程和物理课程成绩都及格的学生id和姓名;

    思路:先过滤出生物或者物理成绩大于60的学生,然后按照学生id分组,

    统计课程id大于1,即为都及格的学生

    SQL:

        (1)select cid from SMS_course where cname in ('生物','物理')

        (2)select student_id from SMS_score where cid in(...) AND

    score >= 60 GROUP BY student_id HAVING COUNT(score)>1

        (3)select sid, sname from SMS_student where sid in(...)

    Python:

        res = Score.objects.filter(course__cname__in=['生物', '物理'],

    score__gte=60).values('student_id').annotate(c=Count('student_id')).

    filter(c__gt=1).values('student_id', 'student__sname')

     

    3.查询每个年级的班级数,取出班级数最多的前三个年级;

    思路:按年级分组,统计每个年级的总班级数,根据班级数降序排列,取前三个年级

    SQL:

        (1)select count(cid) as num, grade_id from SMS_classes group by grade_id

    order by num DESC limit 3;

        (2)select gname, num from(...)as t2 left join SMS_classgrade on t2.grade_id=gid;

    Python:

        res = Classes.objects.values('grade_id').annotate(num=Count('cid')).order_by

    ('-num').values('grade__gname','num')[:3]

     

    4.查询平均成绩最高的学生的id和姓名以及平均成绩;

    思路:按照学生id进行分组,统计每个学生的平均成绩,然后根据成绩降序排列,取第一个

    SQL:

        (1)select student_id,avg(score)as avg_score from SMS_score group by student_id

    order by avg_score desc limit 1;

        (2)select sid,sname,avg_score from(...)left join SMS_student on student_id=sid

    Python:

        res = Score.objects.values('student_id', 'student__sname').annotate

    (avg_score=Avg('score')).order_by('-avg_score')[0]

     

    5.查询每个年级的学生人数;

    思路:按照年级分组,跨表统计学生人数

    SQL:

        (1)select count(sid) from SMS_classes left join SMS_student Ss

    on SMS_classes.cid = Ss.classes_id group by grade_id;

        (2)select gname, total from(...)left join SMS_classgrade on gid=grade_id;

    Python:

        res = Student.objects.values('classes__grade__gid',

    'classes__grade__gname').annotate(total=Count('sid'))

     

    6.查询每位学生的学号,姓名, 平均成绩;

    思路:按照学生分组,统计平均成绩

    SQL:

        select SMS_student.sid,sname,avg(score)as avg_score from

    SMS_student left join SMS_score Ss on SMS_student.sid =

    Ss.student_id group by SMS_student.sid;

    Python:

        res = Score.objects.values('student_id','student__sname').

    annotate(avg_score=Avg('score'))

     

    7.查询学生编号为“2”的学生的姓名、该学生成绩最高的课程名及分数;

    思路:先按pk值过滤出该学生,然后按照成绩排序取出成绩最高值的学科

    SQL:

        (1)select sid, sname from SMS_student where sid=2;

        (2)select * from(...)as s2 left join SMS_score on s2.sid=student_id

    order by score desc limit 1;

        (3)select sid,sname,cname,score from(...) left join SMS_course on course_id=cid;

    Python:

        res = Student.objects.filter(pk=2).values('sid', 'sname', 'score__course__cname',

    'score__score').order_by('-score__score')[0]

     

    8.查询姓的老师所带班级数;

    思路:先过滤除姓任的老师,然后根据老师的任职表统计出班级数

    SQL:

        (1)select * from SMS_teacher where tname like '%'

        (2)select tid,tname,count(classes_id)as class_count from (...)left join

    SMS_teacher_classes on tid=teacher_id group by tid

    Python:

        res = Teacher.objects.filter(tname__startswith='').

    values('tname').annotate(class_count=Count('classes'))

     

     

    9.查询班级数小于3的年级id和年级名;

    思路:先按年级进行分组,得到每个年级的班级数,再按条件进行过滤即可

    SQL:

        (1)select * from SMS_classes group by grade_id having count(cid)<3;

        (2)select gid,gname,class_count from(...)left join SMS_classgrade

    on grade_id=gid;

    Python:

        res = Classes.objects.values('grade_id', 'grade__gname').

    annotate(class_count=Count('cid')).filter(class_count__lt=3)

     

     

    10.查询教过课程超过2门的老师的id和姓名;

    思路:按照老师分组,统计出所教的课程数,进行过滤即可

    SQL:

        (1)select teacher_id,count(cid)as course_count from SMS_course

    group by teacher_id having count(cid)>=2;

    (2)select tid,tname,course_count from(...)left join SMS_teacher on teacher_id=tid;

    Python:

        res = Course.objects.values('teacher__tid', 'teacher__tname').

    annotate(course_count=Count('cid')).filter(course_count__gte=2)

     

     

    11.查询学过编号“1”课程和编号“2”课程的同学的学号、姓名;

    思路:先过滤出学过1或者学过2课程的同学,然后按照学生分组,统计课程数大于1的学生即是都学过的学生

    SQL:

        (1)select student_id from SMS_score where course_id in (1,2)

    group by student_id having course_count=2;

        (2)select sid, sname, course_count from(...)left join SMS_student on student_id=sid;

    Python:

        res = Score.objects.filter(course_id__in=[1,2]).values('student_id','student__sname').

    annotate(course_count=Count('course_id')).filter(course_count=2)

     

     

    12.查询所带班级数最多的老师id和姓名;

    思路:先按老师进行分组,统计出每个老师所带的班级数,

    按照所带班级数进行降序排列然后取第一个即可

    SQL:

        (1)select teacher_id,count(classes_id)as course_count from SMS_teacher_classes

    group by teacher_id order by count(classes_id) desc;

        (2)select tid,tname,course_count from(...)left join SMS_teacher on teacher_id=tid;

    Python:

        res = Teacher.objects.values('tid', 'tname').annotate(

    class_count=Count('classes')).order_by('-class_count')[0]

     

    13.查询有课程成绩小于60分的同学的学号、姓名;

    思路:在成绩表中先过滤出成绩小于60的同学,然后去重即可

    SQL:

        1.select student_id, score from SMS_score where score<60;

        2.select sid,sname,score from(...)left join SMS_student on student_id=sid;

    Python:

        res = Score.objects.filter(score__lt=60).values('student__sid',

    'student__sname', 'score').distinct()

     

    14.查询男生、女生的人数,按倒序排列;

    思路:先按性别进行分组,进行计数,最后按降序排列即可

    SQL:

        select gender, count(sid)as gender_count from SMS_student

    group by gender order by count(sid) desc;

    Python:

        res = Student.objects.values('gender').annotate

    (gender_count=Count('sid')).order_by('-gender_count')

     

     

    15.查询各个课程及相应的选修人数;

    思路:根基成绩表,按照课程进行分组,统计选修人数即可

    SQL:

        (1)select course_id, count(student_id)as student_count from SMS_score

    group by course_id;

        (2)select cid, cname, student_count from(...)left join SMS_course

    on course_id=cid;

    Python:

        res = Score.objects.values('course_id', 'course__cname'

    ).annotate(student_count=Count('student_id'))

     

    16.查询同时选修了物理课和生物课的学生id和姓名;

    思路:同第12

    SQL:

        1.select cid from SMS_course where cname in ('物理', '生物');

        2.select student_id from SMS_score where course_id in (...)group by

    student_id HAVING count(course_id)>1;

        3.select sid, sname from SMS_student where sid in (...);

    Python:

        res = Score.objects.filter(course__cname__in=['物理', '生物']).values(

    'student__sid', 'student__sname').annotate(course_count=Count

    ('course_id')).filter(course_count__gt=1)

     

    17.检索“3”课程分数小于60,按分数降序排列的同学学号;

    思路:先按条件过滤出学生,然后按分数降序即可

    SQL:

        select student_id, score from SMS_score where course_id=3 and score<60

    order by score desc;

    Python:

        res = Score.objects.filter(course_id=3, score__lt=60).values('student_id', 'score')

     

    18.查询每门课程的平均成绩,结果按平均成绩升序排列,

    平均成绩相同时,按课程号降序排列;

    思路:按照课程分组,求出平均成绩,然后排序即可

    SQL:

        1.select course_id, avg(score)as avg_score from SMS_score group by course_id

    order by avg_score,course_id desc;

        2.select cid,cname,avg_score from(...)left join SMS_course on course_id=cid;

    Python:

        res = Score.objects.values('course_id', 'course__cname').annotate(avg_score=

    Avg('score')).order_by('avg_score','-course_id')

     

    19.查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分;

    思路:在成绩表按照课程分组,计算出分数最高分和最低分,完成显示即可

    SQL:

        1.select *, max(score)as max_score, min(score)as min_score from SMS_score group by course_id;

        2.select cid,cname,max_score,min_score from(...)left join SMS_course on cid=course_id;

    Python:

        res = Score.objects.values('course_id', 'course__cname').

    annotate(max_score=Max('score'), min_score=Min('score'))

  • 相关阅读:
    [博客美化]给你博客添加一个萌萌的看板娘吧
    精简Command版SqlHelper
    使用VS2017创建EF框架实例
    Ueditor1.4.3.3 asp UTF-8版文件缺失修改方法
    android studio编译包真机安装失败解决方案记录
    ANDROID开发之问题积累及解决方案(四)
    ANDROID开发之问题积累及解决方案(三)
    ANDROID调用webservice带soapheader验证
    ANDROID开发之问题积累及解决方案(二)
    ANDROID开发之问题积累及解决方案(一)
  • 原文地址:https://www.cnblogs.com/hszstudypy/p/11294025.html
Copyright © 2011-2022 走看看