自定义类实现原生SQL的GROUP_CONCAT的功能
大家都知道,原生的SQL为我们提供了分组之后查找组内数据的办法:GROUP_CONCAT方法;但是对于用Django开发的程序员来说~Django自带的ORM并没有内置这样功能的方法,而每一次遇到这样的需求如果都要用原生SQL去解决的话势必会降低我们的开发效率。
本文为大家介绍一种在Django项目中自定义类Coucat类的方式去实现对应的效果。
表关系
现在假设我们的Django项目的book应用中有两张关联的表:book表与publish表。表结构如下:
book表:

publish表:

其中:book表的publisher_id是通过ORM语法与publish表建立关联的外键字段。
原生SQL中GROUP_CONCAT的分组查询
单表下的分组查询
按照publisher_id分组查询每组数据下的书名:
select group_concat(title),publisher_id from book_book GROUP BY(publisher_id);
结果如下:

连表下的分组查询
查找每个出版社出版的书籍的名称
select group_concat(book_book.title),book_publish.name from book_book inner join book_publish
on book_book.publisher_id = book_publish.id
group by book_publish.name;
结果如下:

ORM中自定义Concat类实现COUCAT_GROUP的效果
在我们Django项目中的lib目录下新建一个concat.py文件,文件中的内容如下:
# -*- coding:utf-8 -*-
from django.db.models import Aggregate,CharField class Concat(Aggregate):
function = 'GROUP_CONCAT'
template = '%(function)s(%(distinct)s%(expressions)s)' def __init__(self,expression,distinct=False,**extra):
super(Concat,self).__init__(
expression,
distinct='DISTINCT' if distinct else '',
output_field=CharField(),
**extra)
以上的代码就是我们实现COUCAT_GROUP效果的类。
然后,创建一条测试路由:
url(r'^concat/',views.concat),
视图函数中concat函数实现具体的功能:
from django.shortcuts import HttpResponse
from lib.concat import Concat
def concat(request):
# 单表:用publisher_id分组,找每个分组中的书籍名称
ret = Book.objects.values('publisher_id').annotate(titles=Concat('title'))
print(ret)
#<QuerySet [{'publisher_id': 21, 'titles': 'linux,cpp,lsi'}, {'publisher_id': 22, 'titles': 'ruby,c'},
# {'publisher_id': 23, 'titles': 'go,xsd'}, {'publisher_id': 24, 'titles': 'java'}, {'publisher_id': 25, 'titles': 'python,rsb'}]>
#跨表:每个出版社出版的所有的书籍
#方法一:以publish表为基准去查
ret = Publish.objects.values('name').annotate(titles=Concat('book__title'))
print(ret)
#<QuerySet [{'name': '樱桃出版社', 'titles': 'go,xsd'}, {'name': '橘子出版社', 'titles': 'ruby,c'},
# {'name': '橙子出版社', 'titles': 'python,rsb'}, {'name': '苹果出版社', 'titles': 'linux,cpp,lsi'}, {'name': '西瓜出版社', 'titles': 'java'}]>
#方法二:以book表为基准去查
ret = Book.objects.values('publisher__name').annotate(titles=Concat('title'))
print(ret)
#<QuerySet [{'publisher__name': '樱桃出版社', 'titles': 'go,xsd'}, {'publisher__name': '橘子出版社', 'titles': 'ruby,c'},
# {'publisher__name': '橙子出版社', 'titles': 'python,rsb'}, {'publisher__name': '苹果出版社', 'titles': 'linux,cpp,lsi'},
# {'publisher__name': '西瓜出版社', 'titles': 'java'}]>
return HttpResponse('Concat')
大家可以看到,用法也十分简单,只需要在分组的annotate方法中加上我们定义的这个类就可以了~
自定义类实现原生SQL的GROUP_CONCAT的功能的更多相关文章
- Java基础知识强化之IO流笔记55:IO流练习之 自定义类模拟LineNumberReader的获取行号功能案例
1. 自定义类模拟LineNumberReader的获取行号功能案例 2. 代码实现: (1)MyBufferedReader.java: package cn.itcast_08; import j ...
- legend---十、thinkphp中如何进行原生sql操作
legend---十.thinkphp中如何进行原生sql操作 一.总结 一句话总结:query方法和execute方法 Db类支持原生SQL查询操作,主要包括下面两个方法: query方法 quer ...
- jpa 联表查询 返回自定义对象 hql语法 原生sql 语法 1.11.9版本
-----业务场景中经常涉及到联查,jpa的hql语法提供了内连接的查询方式(不支持复杂hql,比如left join ,right join). 上代码了 1.我们要联查房屋和房屋用户中间表,通过 ...
- springdata 查询思路:基本的单表查询方法(id,sort) ---->较复杂的单表查询(注解方式,原生sql)--->实现继承类---->复杂的多表联合查询 onetomany
springdata 查询思路:基本的单表查询方法(id,sort) ---->较复杂的单表查询(注解方式,原生sql)--->实现继承类---->复杂的多表联合查询 onetoma ...
- 使用原生SQL返回实体类具体实现详情
注:可以直接复制粘贴,欢迎提出各种问题,谢谢! 因为网上查询大都是相同的,自己做时发现很多不懂,摸索了很久才弄懂,所以写了这个例子,比较容易看懂吧. 使用原生SQL查询并将结果返回实体中: (1)因为 ...
- hibernate使用原生SQL查询
以下是Demo测试Hibernate 原生SQL查询: import java.util.Iterator; import java.util.List; import java.util.Map; ...
- 关于No Dialect mapping for JDBC type :-9 hibernate执行原生sql语句问题
转自博客http://blog.csdn.net/xd195666916/article/details/5419316,同时感谢博主 今天做了个用hibernate直接执行原生sql的查询,报错No ...
- 2016/05/13 thinkphp 3.2.2 ① 数据删除及执行原生sql语句 ②表单验证
[数据删除及执行原生sql语句] delete() 返回受影响的记录条数 $goods -> delete(30); 删除主键值等于30的记录信息 $goods -> delete( ...
- Django&,Flask&pyrthon原生sql语句 基本操作
Django框架 ,Flask框架 ORM 以及pyrthon原生sql语句操作数据库 WHAT IS ORM? ORM( Object Relational Mapping) 对象关系映射 , 即通 ...
随机推荐
- 关系型数据库为什么喜欢使用B+树作为索引结构? (转)
问题1. 数据库为什么要设计索引? 图书馆存了1000W本图书,要从中找到<架构师之路>,一本本查,要查到什么时候去? 于是,图书管理员设计了一套规则: (1)一楼放历史类,二楼放文学类, ...
- W3C标准下的盒模型与IE盒模型
标准盒模型如下图所示: IE下盒模型如下图所示:
- Windows系统如何安装Redis
转自 http://blog.csdn.net/lamp_yang_3533/article/details/52024744 一.Redis的下载地址 Redis官方并没有提供Redis的windo ...
- 【React 8/100】 React路由
React路由 React路由介绍 现代的前端应用大多数是SPA(单页应用程序),也就是只有一个HTML页面的应用程序.因为它的用户体验更好.对服务器压力更小,所以更受欢迎.为了有效的使用单个页面来管 ...
- postman中x-www-form-urlencoded与form-data的区别
这是W3C定义的两种不同的表格类型,如果你想发送简单的text/ASCII数据,使用x-www-form-urlencoded , 这是默认的形式. 如果你想发送非ASCII文本或者大的二进制数据,使 ...
- MongoDB的使用学习之(六)MongoDB的高级查询之条件操作符
此文分为两点,主要是在第二点--java 语法,但是按顺序必须先把原生态的语法写出来 (还有一篇文章也是不错的:MongoDB高级查询用法大全(包含MongoDB命令语法和Java语法,其实就是我整理 ...
- Spring基础05——Spring依赖注入的三种方式
Spring支持3种依赖注入的方式:属性注入.构造器注入.工厂 1.属性注入 属性注入即通过setter方法注入Bean的属性或依赖的对象.使用<property>元素,使用name属性指 ...
- 001-supervisor
supervisor 使用教程(转) 原文地址:https://word.gw1770df.cc/2016-08-04/linux/supervisor-%E4%BD%BF%E7%94%A8%E6%9 ...
- 感想 - 猴子刷视频app
看到一个视频,内容是一只猿猴熟练地像人一样刷短视频app,惟妙惟肖:https://pan.baidu.com/s/10-eibLmuybKtRJ-CKnruYA 抽象思考和语言才是人类独有的能力,视 ...
- 主流Linux发行版及联系
一.主流Linux主流发行版 RedHat:Red Hat Linux是由Red Hat公司发行的一个Linux发行包.其1.0版本于1994年11月3日发行,虽然其历史不及Slackware般悠久, ...