• Django笔记二十四之数据库函数之比较和转换函数


    本文首发于公众号:Hunter后端
    原文链接:Django笔记二十四之数据库函数之比较和转换函数

    这一篇笔记开始介绍几种数据库函数,以下是几种函数及其作用

    1. Cast 转换类型
    2. Coalesce 优先取值
    3. Greatest 返回较大值
    4. Nullif 值相同返回 None

    1、model 准备

    这一篇笔记我们主要用到 Author 和 Entry model 作为示例,下面的是 Author model:

    class Author(models.Model):
        name = models.CharField(max_length=200)
        email = models.EmailField(null=True, default=None)
        age = models.IntegerField(null=True, blank=True)
        alias = models.CharField(max_length=50, null=True, blank=True)
        goes_by = models.CharField(max_length=50, null=True, blank=True)
    

    一般来说,对于 CharField 字段,我们是不推荐允许 null=True 存在的,因为这样的话,在数据库中就会存在两个空值,一个是 null,一个是空字符串 ''。

    在这里允许这样操作是为了方便的介绍下面的功能。

    注意下,数据库相关函数都是在 django.db.models.functions 模块下

    2、Cast 转换类型

    Cast 的作用,我们可以将其理解成转换数据类型,比如在 Author 中,age 字段是一个 Integer 数据。

    但是如果我们想要获取数据的时候想要将其直接变成浮点型数据,就可以使用 Cast() 函数,通过 output_field=FloatField() 参数来指定输出类型。

    # 先创建数据
    from blog.models import Author
    Author.objects.create(name='hunter', age=25)
    

    返回一个新字段,通过 Cast() 函数来指定输出类型:

    from django.db.models import FloatField
    from django.db.models.functions import Cast
    
    author = Author.objects.annotate(float_age=Cast('age', output_field=FloatField())).get(id=1)
    print(author.float_age)
    

    最后的输出就是一个浮点型数据了。

    3、Coalesce 优先取值

    Coalesce 的单词的含义是 合并、联合,但是在这里函数表现出的意义是,优先取值。

    Coalesce() 接受多个字段或者表达式作为参数,至少为两个字段名称,然后会返回第一个非 null 的字段的值(注意: 空字符串 '' 不被认为是 null 值)

    每个元素都必须是相似的类型,否则会引起报错。

    对于 Author 这个model,我们想要按照 alias, goes_by, name 三个字段的这个顺序来取值。

    也就是说 有alias 字段就取 alias 的内容,否则取 goes_by 的字段值,goes_by 也没有 就取 name 字段,这种情况就可以使用 Coalesce() 来操作。

    先来创建几条数据:

    Author.objects.create(alias="alias-1", goes_by='goes-by-1', name='name-1')
    Author.objects.create(goes_by='goes-by-2', name='name-2')
    Author.objects.create(name='name-3')
    Author.objects.create(alias="", goes_by='goes-by-4', name='name-4')
    

    以上三条数据的 id 在数据库分别是 2,3,4,5

    接下来可以测试一下 Coalesce() 这个函数

    from django.db.models.functions import Coalesce
    
    author = Author.objects.annotate(new_field=Coalesce('alias', 'goes_by', 'name')).get(id=2)
    print(author.new_field)
    # 输出 alias-1
    
    author = Author.objects.annotate(new_field=Coalesce('alias', 'goes_by', 'name')).get(id=3)
    print(author.new_field)
    # 输出 goes-by-2
    
    author = Author.objects.annotate(new_field=Coalesce('alias', 'goes_by', 'name')).get(id=4)
    print(author.new_field)
    # 输出 name-3
    
    author = Author.objects.annotate(new_field=Coalesce('alias', 'goes_by', 'name')).get(id=5)
    print(author.new_field)
    # 输出 空字符串 ''
    

    以上几个例子,我们就测试出了新建字段的取值优先顺序,以及空字符串和 null 在这个函数里的区别(会跳过值为 null 的数据,但是会取空字符串的字段值)。

    空值的默认值

    其实用到这里,我们可以发现这个函数的另一个用法,那就是 null 值下替换的默认值。

    假设我们有一个字段,我们在取值的时候,想实现,如果该字段是 null,那么我们在取值的时候就想将其替换成另一个默认值,而不是返回 null 或者后续在内存中操作替换默认值,可以这样操作:

    from django.db.models import Value
    author = Author.objects.annotate(new_field=Coalesce('email', Value('xxx'))).get(id=5)
    print(author.new_field)
    
    # id 等于 5 的 Author 数据,email 字段为空,所以 new_field 的值被替换成了 'xxx'
    

    默认值的处理也可以用在聚合中,比如聚合 Sum() 的时候,如果没有满足条件的数据,聚合的结果会是一个 null,但是我们可以自动将其变为 0:

    from django.db.models import Sum, Value
    Author.objects.aggregate(age_sum=Coalesce(Sum('age'), Value(0)))
    

    4、Greatest 返回较大值

    Greatest() 的用法与 Coalesce 相同,接受两个或多个类型相同的元素,返回最大的一个。

    可以比较数字,和时间等字段类型。

    这里示例我们使用 Entry model,我们只用两个整型字段:

    class Entry(models.Model):
        number_of_comments = models.IntegerField()
        number_of_pingbacks = models.IntegerField()
    

    用法如下:

    from blog.models import Entry
    from django.db.models.functions import Greatest
    
    Entry.objects.annotate(max_value=Greatest("number_of_comments", "number_of_pingbacks")).get(id=2).max_value
    
    # max_value 字段取值就会是number_of_comments 和 number_of_pingbacks 之间最大的
    

    这里我们也可以挖掘出一个骚操作,那就是取值的下限

    比如这两个字段的值都没有达到我们想要的阈值,比如说是2,我们希望返回的值至少是2,可以这样设计程序:

    Entry.objects.annotate(max_value=Greatest("number_of_comments", "number_of_pingbacks", Value(2))).get(id=2).max_value
    

    注意: 在MySQL 和 Oracle 中,如果 Greatest 中,只要有一个字段值为 null,那么结果就会返回 null,这一点一定要注意

    Least() 这个取的是最小值,与 Greatest 作用是相反的,但用法是一样的,不多介绍

    5、Nullif 值相同返回 None

    获取两个字段,也可以是表达式的结果,或者是 Value() 的值,但两者的数据类型得一致,用于判断两者的值是否相同。

    如果两者的值相同,则返回 Python 里的 None,不相同的话返回第一个表达式的值

    用法示例如下:

    Entry.objects.annotate(new_field=NullIf("number_of_comments", "number_of_pingbacks")).get(id=1).new_field
    
    Entry.objects.annotate(new_field=NullIf("number_of_comments", Value(2))).get(id=1).new_field
    

    以上就是本篇笔记全部内容,下一篇将介绍数据库函数之日期函数

    如果想获取更多后端相关文章,可扫码关注阅读:
    image

  • 相关阅读:
    语言基础篇8——表达式,多种多样的表达方式
    简单了解:什么是低代码?
    如何使用css实现一个加载动画
    【Tomcat&http&servlet】
    JavaWeb之js
    前端学习笔记002:CSS3
    【入门Flink】- 06Flink作业提交流程【待完善】
    springboot 配置 servlet filter 2
    Adobe Indesign 操作
    vCenter7.0 为分布式交换机VDS配置链路聚合(LACP)
  • 原文地址:https://www.cnblogs.com/hunterxiong/p/17331444.html