赞
踩
班级表:
学生表:
result = db.session.query(Student.id,Student.name,Student.gender,Student.age,Student.classes).limit(10).all()
对应的SQL和结果:
- SELECT student.id AS student_id, student.name AS student_name, student.gender AS student_gender, student.age AS student_age, student.classes AS student_classes
- FROM student
- LIMIT ? OFFSET ?
-
- [(1, '张三', 'male', '18', 'java'), (2, '李四', 'female', '19', 'c++'), (3, '王五', 'male', '22', 'php'), (4, '赵六', 'female', '25', 'matalab'), (5, 'lee', 'man', '18', 'python'), (6, '张三', 'male', '18', 'java'), (7, '李四', 'female', '19', 'c++'), (8, '王五', 'male', '22', 'php'), (9, '赵六', 'female', '25', 'matalab'), (10, 'lee', 'man', '18', 'python')]
- restult = db.session.query(Student.id,Student.name,Student.gender,Student.age,Student.classes).filter(Student.classes=='java').filter(Student.gender=='female')
- print(restult)
- print(result..all())
返回的SQL和对应的结果:
- SELECT student.id AS student_id, student.name AS student_name, student.gender AS student_gender, student.age AS student_age, student.classes AS student_classes
- FROM student
- WHERE student.classes = ? AND student.gender = ?
-
- 结果:[(11, '胡和', 'female', '18', 'java')]
- task_filter = {
- or_(
- and_(Student.gender=='female',
- Student.classes=='java'
- ),
- and_(
- Student.age == 18,
- Student.classes == 'python'
- )
- )
- }
- restult2 = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes).filter(*task_filter).all()
- print(restult2)
返回的SQL和对应的结果:
- SELECT student.id AS student_id, student.name AS student_name, student.gender AS student_gender, student.age AS student_age, student.classes AS student_classes
- FROM student
- WHERE student.gender = ? AND student.classes = ? OR student.age = ? AND student.classes = ?
-
- [(5, 'lee', 'male', '18', 'python'),
- (10, '乐奋', 'male', '18', 'python'),
- (11, '胡和', 'female', '18', 'java')]
上面这个filter中有两个条件组,关系为or,每个条件组里有一些and关系的条件。
- restult3 = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes, Grades.grade).filter(
- Student.classes == 'java').filter(Student.gender == 'male').filter(Student.cls_id == Grades.id).all()
返回的SQL和对应的结果:
- SELECT student.id AS student_id, student.name AS student_name, student.gender AS student_gender, student.age AS student_age, student.classes AS student_classes, grades.grade AS grades_grade
- FROM student, grades
- WHERE student.classes = ? AND student.gender = ? AND student.cls_id = grades.id
-
- [(6, '张三', 'male', '18', 'java', '一年级(3)班')]
- task_filter={
- and_(Student.gender == 'male',
- Student.classes == 'python')
- }
- restult4 = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes).filter(*task_filter).count()
- print(restult4)
返回的SQL和对应的结果:
- SELECT
- count(*) AS count_1
- FROM
- (
- select……from……where ……and……
- )
- AS anon_1
-
- 结果为:4
进行优化后的func.count()函数: 无子查询,效率高
- restult5 = db.session.query(func.count(Student.id)).filter(*task_filter).scalar()
- print(db.session.query(func.count(Student.id)).filter(*task_filter))
- print(restult5)
返回的SQL和对应的结果:
- select count(Student.id) as count_1
- FROM
- student
- WHERE
- student.gender = ? AND student.classes = ?
-
- 结果为:4
- query = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes, Grades.grade).join(Grades,Student.cls_id==Grades.id).filter(*task_filter).order_by(Student.id).limit(2)
- print(query)
- print(query.all())
返回的SQL和结果:
- SELECT student.id AS student_id, student.name AS student_name, student.gender AS student_gender, student.age AS student_age, student.classes AS student_classes, grades.grade AS grades_grade
- FROM student JOIN grades ON student.cls_id = grades.id
- WHERE student.gender = ? AND student.classes = ? ORDER BY student.id
- LIMIT ? OFFSET ?
- [(6, '张三', 'male', '18', 'java', '一年级(3)班')]
- #返回指定的一列
- query1 = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes).with_entities(Student.classes).distinct().all()
- print(db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes).with_entities(Student.classes).distinct())
- print(query1)
- #返回指定的两列
- query = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes).with_entities(Student.classes,Student.cls_id).distinct().all()
返回对应的sql和查询结果:
- SELECT DISTINCT student.classes AS student_classes
- FROM student
- [('java',), ('c++',), ('php',), ('matalab',), ('python',), ('C',)]
- query = Student.query.join(Grades,and_(Student.cls_id==Grades.id)).filter(Student.classes=='python').with_entities(Student.name,Grades.grade)
- print(query) #打印SQL
- results = query.all()
- print(results) #打印结果
- data = [dict(zip(result.keys(), result)) for result in results]
- print(data) #将结果转为dict
对应结果如下:
- SELECT student.name AS student_name, grades.grade AS grades_grade
- FROM student JOIN grades ON student.cls_id = grades.id
- WHERE student.classes = 'python'
-
- [('乐奋', '一年级(5)班'), ('石雨', '一年级(5)班'), ('马庆', '一年级(1)班'), ('刘胜', '一年级(4)班')]
-
- [{'name': '乐奋', 'grade': '一年级(5)班'}, {'name': '石雨', 'grade': '一年级(5)班'}, {'name': '马庆', 'grade': '一年级(1)班'}, {'name': '刘胜', 'grade': '一年级(4)班'}]
除了筛选字段外,还可以用另一个方法获取多个 Model 的记录。那就是,返回两个 Model 的所有字段:
- query = db.session.query(Student,Grades).join(Grades,and_(Student.cls_id==Grades.id)).filter(Student.classes=='python')
- print(query)
- restult = query.all()
- print(restult)
返回的SQL和结果:
- SELECT student.id AS student_id, student.name AS student_name, student.age AS student_age, student.gender AS student_gender, student.classes AS student_classes, student.cls_id AS student_cls_id, grades.id AS grades_id, grades.name AS grades_name, grades.grade AS grades_grade
- FROM student JOIN grades ON student.cls_id = grades.id
- WHERE student.classes = 'python'
- [(<Student 10>, <Grades 5>), (<Student 15>, <Grades 5>), (<Student 16>, <Grades 8>), (<Student 17>, <Grades 9>)]
使用上面的语法直接返回 Account 和 Bind 对象,可以进行更加灵活的操作。
- student = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes).group_by("classes").all() # 按照组
- print(db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes).group_by("classes"))
- print(student)
对应的SQL和group_by查询结果:
- SELECT student.id AS student_id, student.name AS student_name, student.gender AS student_gender, student.age AS student_age, student.classes AS student_classes
- FROM student GROUP BY student.classes
- [(18, '贾华', 'female', '19', 'C'), (12, '李天', 'male', '19', 'c++'), (11, '胡和', 'female', '18', 'java'), (14, '李广', 'male', '24', 'matalab'), (13, '陈安', 'male', '26', 'php'), (17, '刘胜', 'male', '25', 'python')]
- query = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes).order_by(Student.age.desc())
- print(query)
- print(query.all())
对应的SQL和返回结果:
- SELECT student.id AS student_id, student.name AS student_name, student.gender AS student_gender, student.age AS student_age, student.classes AS student_classes
- FROM student ORDER BY student.age DESC
- [(13, '陈安', 'male', '26', 'php'), (4, '赵六', 'female', '25', 'matalab'), (9, '赵六', 'female', '25', 'matalab'), (17, '刘胜', 'male', '25', 'python'), (14, '李广', 'male', '24', 'matalab'), (3, '王五', 'male', '22', 'php'), (8, '王五', 'male', '22', 'php'), (16, '马庆', 'male', '22', 'python'), (1, '张三', 'male', '20', 'java'), (2, '李四', 'female', '19', 'c++'), (7, '李四', 'female', '19', 'c++'), (12, '李天', 'male', '19', 'c++'), (18, '贾华', 'female', '19', 'C'), (5, 'lee', 'male', '18', 'python'), (6, '张三', 'male', '18', 'java'), (10, '乐奋', 'male', '18', 'python'), (11, '胡和', 'female', '18', 'java'), (15, '石雨', 'female', '17', 'python')]
- query = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes,Grades.grade).join(Grades,Student.cls_id==Grades.id).filter(Student.name.like('%李%'))
- print(query)
- print(query.all())
非外键连接,表student与表grades内连接inner join
对应的SQL和返回结果:
- SELECT student.id AS student_id, student.name AS student_name, student.gender AS student_gender, student.age AS student_age, student.classes AS student_classes, grades.grade AS grades_grade
- FROM student JOIN grades ON student.cls_id = grades.id
- WHERE student.name LIKE "%李%"
- [(7, '李四', 'female', '19', 'c++', '一年级(2)班'), (12, '李天', 'male', '19', 'c++', '一年级(2)班'), (14, '李广', 'male', '24', 'matalab', '一年级(3)班')]
还可以在 filter 得到结果后继续加 join 进行多表联查
query = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes,Grades.grade).outerjoin(Grades,Student.cls_id==Grades.id).filter(Student.name.like('%李%'))
- SELECT student.id AS student_id, student.name AS student_name, student.gender AS student_gender, student.age AS student_age, student.classes AS student_classes, grades.grade AS grades_grade
- FROM student LEFT OUTER JOIN grades ON student.cls_id = grades.id
- WHERE student.name LIKE ?
-
- [(2, '李四', 'female', '19', 'c++', None), (7, '李四', 'female', '19', 'c++', '一年级(2)班'), (12, '李天', 'male', '19', 'c++', '一年级(5)班'), (14, '李广', 'male', '24', 'matalab', '一年级(3)班')]
outerjoin相当于LEFT OUTER JOIN 左外连接;outerjoin( ) 返回结果有null
- query = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes,Grades.grade).join(Grades,and_(Student.cls_id==Grades.id,Student.classes=='python',Grades.grade=='一年级(5)班'))
- print(query)
- print(query.all())
对应的SQL和返回结果:
- SELECT student.id AS student_id, student.name AS student_name, student.gender AS student_gender, student.age AS student_age, student.classes AS student_classes, grades.grade AS grades_grade
- FROM student JOIN grades ON student.cls_id = grades.id
- AND student.classes = "python"
- AND grades.grade = "一年级(5)班"
-
- [(10, '乐奋', 'male', '18', 'python', '一年级(5)班'), (15, '石雨', 'female', '17', 'python', '一年级(5)班')]
这里只有两张表,如果是三张表继续在后面join()即可。
要联结超过 2 张以上的表,可以直接在 join 得到的结果之后链式调用 join 。也可以在 filter 的结果后面链式调用 join 。join 和 filter 返回的都是 query 对象,因此可以无限链式调用下去。
没有设置外键:
- query = db.session.query(Student.id, Student.name, Student.gender,
- Student.age, Student.classes,Grades.grade)
- .join(Grades,Student.cls_id==Grades.id)
- .filter(Student.name.like('%李%'))
已经设置外键:
- query = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes,
- Grades.grade)
- .join(Grades)
- .filter(Student.name.like('%李%'))
- query = db.session.query(Student).order_by(Student.age.desc()).paginate(1,5)
- print(db.session.query(Student).order_by(Student.age.desc()))
- print(query.items)
- print(query.pages)
- print(query.total)
对应SQL和结果:
- SELECT student.id AS student_id, student.name AS student_name, student.age AS student_age, student.gender AS student_gender, student.classes AS student_classes, student.cls_id AS student_cls_id
- FROM student ORDER BY student.age DESC
- [<Student 13>, <Student 4>, <Student 9>, <Student 17>, <Student 14>]
这里的结果返回的是model对象,需要在query()括号里明确字段:
- query = db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes).order_by(Student.age.desc()).paginate(1,5)
- print(db.session.query(Student.id, Student.name, Student.gender, Student.age, Student.classes).order_by(Student.age.desc()))
- print(query.items)
返回的是第一页前5个的结果:
[(13, '陈安', 'male', '26', 'php'), (4, '赵六', 'female', '25', 'matalab'), (9, '赵六', 'female', '25', 'matalab'), (17, '刘胜', 'male', '25', 'python'), (14, '李广', 'male', '24', 'matalab')]
- query = db.session.query(Student.id, Student.name).filter(Student.id.in_([1,3,4]))
- print(query.all())
- query = db.session.query(Student.id, Student.name,Student.age).filter(Student.age.notin_([18, 19, 20,22]))
- print(query.all())
返回结果:
- [(1, '张三'), (3, '王五'), (4, '赵六')]
- [(4, '赵六', '25'), (9, '赵六', '25'), (13, '陈安', '26'), (14, '李广', '24'), (15, '石雨', '17'), (17, '刘胜', '25')]
- #组合 union与union_all函数 组合的字段数量应一致
- query1 = db.session.query(Student.id, Student.name).filter(Student.age>22)
- query2 = db.session.query(Grades.id,Grades.name).filter(Grades.id>1).distinct()
- print(query1.union(query2))
- print(query1.union(query2).all()) #union默认会去重
- res = query1.union_all(query2).all() #union_all默认不去重
- print(res)
对应SQL和结果:
- SELECT anon_1.student_id AS anon_1_student_id, anon_1.student_name AS anon_1_student_name
- FROM (SELECT student.id AS student_id, student.name AS student_name
- FROM student
- WHERE student.age > ? UNION SELECT grades.id AS grades_id, grades.name AS grades_name
- FROM grades
- WHERE grades.id > ?) AS anon_1
- [(2, '李四'), (3, '王五'), (4, '赵六'), (5, 'lee'), (6, '张三'), (7, '李四'), (8, '王五'), (9, '赵六'), (10, 'lee'), (11, '张三'), (12, '李四'), (13, '王五'), (13, '陈安'), (14, '李广'), (14, '赵六'), (15, 'lee'), (16, '张三'), (17, '刘胜'), (17, '李四'), (18, '王五'), (19, '赵六'), (20, 'lee')]
- [(4, '赵六'), (9, '赵六'), (13, '陈安'), (14, '李广'), (17, '刘胜'), (2, '李四'), (3, '王五'), (4, '赵六'), (5, 'lee'), (6, '张三'), (7, '李四'), (8, '王五'), (9, '赵六'), (10, 'lee'), (11, '张三'), (12, '李四'), (13, '王五'), (14, '赵六'), (15, 'lee'), (16, '张三'), (17, '李四'), (18, '王五'), (19, '赵六'), (20, 'lee')]
- query = db.session.query(Student.classes,func.count(Student.name).label("cnt")).group_by('classes').order_by(desc('cnt'))
- print(query)
- print(query.all())
返回的SQL和结果:
- SELECT student.classes AS student_classes, count(student.name) AS cnt
- FROM student GROUP BY student.classes ORDER BY cnt DESC
- [('python', 5), ('c++', 3), ('java', 3), ('matalab', 3), ('php', 3), ('C', 1)]
- query1 = db.session.query(Student,Grades).filter(Student.cls_id.in_(db.session.query(Grades.id).filter(Grades.grade=='一年级(5)班'))).with_entities(Student.id,Student.name,Student.age,Student.gender,Student.classes).distinct()
- print(query1)
- print(query1.all())
返回的SQL和结果:
- SELECT DISTINCT student.id AS student_id, student.name AS student_name, student.age AS student_age, student.gender AS student_gender, student.classes AS student_classes
- FROM student
- WHERE student.cls_id IN (SELECT grades.id AS grades_id
- FROM grades
- WHERE grades.grade = '一年级(5)班')
- [(10, '乐奋', '18', 'male', 'python'), (15, '石雨', '17', 'female', 'python')]
- subquery = db.session.query(func.count(Student.id).label("sid")).filter(Student.cls_id==Grades.id).correlate(Grades).as_scalar()
- #第一步:db.session.query(func.count(Student.id).label("sid")).filter(Student.cls_id==Grades.id)
- #这句话SQL为:SELECT count(student.id) AS sid FROM student WHERE student.cls_id = grades.id #如果直接运行,则会报错
- #第二步:.correlate(Grades).as_scalar() ==> 代表此时不执行查询操作,将其当作条件,在Grades表中查询时,才执行查询
- restult = db.session.query(Grades.name, subquery)
- #sql语句为:select Grades.name subquery from Grades
- print(restult)
- # 第三步:将subquery替换为上面的条件,则此句的SQL为:
- # SELECT grades.name AS grades_name, (SELECT count(student.id) AS sid FROM student WHERE student.cls_id = grades.id) AS anon_1 FROM grades
- print(restult.all())
- if filter_type == 1:
- search = and_(GameRoom.status ==1,or_(
- and_(GameRoom.white_user_id == user_id,
- GameRoom.active_player == 1),
- and_(GameRoom.black_user_id == user_id,
- GameRoom.active_player == 0)))
- elif filter_type == 2:
- search = and_(GameRoom.status ==1,or_(
- and_(GameRoom.white_user_id == user_id,
- GameRoom.active_player == 0),
- and_(GameRoom.black_user_id == user_id,
- GameRoom.active_player == 1)))
- elif filter_type == 3:
- search = GameRoom.create_by == user_id
-
- db.session.query(GameRoom).filter(search).all()
如果查询实在太复杂,觉得用SQLAlchemy查询方式很难实现,或者要通过存储过程实现查询,可以让SQLAlchemy直接运行SQL语句返回结果。
- sql ="""select b.user_id,b.user_name,b.icon,b.score,a.add_score from
- (select user_id, sum(score_new - score_old) as add_score from user_score_log
- where year(create_date)=year(now()) and month(create_date)=month(now())
- group by user_id) a join users b on a.user_id=b.user_id
- order by a.add_score desc limit 50"""
- list_top = db.session.execute(sql).fetchall()
这些查询语句已经解决了大部分的需求。
注:一般写完查询后,应该打印生成的 SQL 语句查看一下有没有性能问题。
- func.sum求和:
- query = db.session.query(func.sum(Student.cls_id))
-
- func.max求最大值:
- query = db.session.query(func.max(Student.cls_id))
-
- func.min求最小值:
- query = db.session.query(func.min(Student.cls_id))
-
- func.avg求平均值:
- query = db.session.query(func.avg(Student.cls_id))
-
- func.count进行统计:
- query = db.session.query(func.count(Student.id))
- from sqlalchemy import or_,and_,func,desc
-
- query = db.session.query(Student.name).filter(Student.id == 6)
-
- query = db.session.query(Student.id).filter(Student.id != 6)
-
- query = db.session.query(Student.name).filter(Student.name.like('%王%'))
-
- query = db.session.query(Student.id, Student.name).filter(Student.id.in_([1,3,4]))
-
- query = db.session.query(Student.id, Student.name,Student.age).filter(Student.age.notin_([18, 19, 20,22]))
-
- query = db.session.query(Student.name).filter(Student.cls_id==None)
-
- query = db.session.query(Student.name).filter(Student.cls_id!=None)
-
- query = db.session.query(Student.name).filter(and_(Student.age==18,Student.classes=='python'))
-
- query = db.session.query(Student.name).filter(or_(Student.age==18,Student.classes=='python'))
-
- print(query) #打印SQL
- print(query.all()) #打印结果
- filter -》 column == expression
- 传入参数的写法,要用:类名.列名 两个等号 去判断
- 举例:
- query(User.name).filter(User.fullname==’Ed Jones’)
- 且更复杂的查询的语法,比如_and(),or_()等多个条件的查询,只支持filter
- 举例:
- query.filter(or_(User.name == ‘ed’, User.name == ‘wendy’))
- query.filter(and_(User.name == ‘ed’, User.fullname == ‘Ed Jones’))
-
- filter_by -》keyword = expression
- 传入参数的写法,只需要用:(不带类名的)列名 单个等号 就可以判断。
- -》filter中,语法更加贴近于,类似于,Python的语法。
- 举例:
- query(User.name).filter_by(fullname=’Ed Jones’)
filter_by() 只接受键值对参数,所以 filter_by() 不支持><(大于和小于)和 and_、or_查询。
在使用多条件匹配的时候,filter需要借助sqlalchemy里的and_ ,or_ ; 而filter_by不需要,直接把多个匹配条件写在一起。
- query = db.session.query(Student.age,func.count(Student.id)).group_by(Student.age).having(Student.age > 20)
- print(query)
- print(query.all())
对应的SQL和结果:
- SELECT student.age AS student_age, count(student.id) AS count_1
- FROM student GROUP BY student.age
- HAVING student.age > ?
- [('22', 3), ('24', 1), ('25', 3), ('26', 1)]
参考链接:https://blog.zengrong.net/post/join-in-flash-sqlalchemy/
https://www.cnblogs.com/huchong/p/8274510.html#_label3_1_1_0
https://www.cnblogs.com/zhongyehai/p/11828337.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。