Pony的left-join

简介: Pony的left-join

1、前言


上篇我们了解了Pony ORM框架的基本用法,今天我们一起来学习下pony的left-join。

left-join使我们日常工作中用的最多的多表联合查询语句,左连接即有两个表A、B,A的keya是B的keyb的外键,那么我们可以通过left-join将B表左连接到A表的左边,通过A表的keya找到能够匹配到keyb的B表内容,未匹配成功的行使用None(null)填充。这样就实现了左连接的查询。


左连接以左表为主,所以左表未匹配成功的行使用None填充。但是结果表的字段我们可以根据自己的需要去选择A表或者B表的字段组合完成。


2、快速开始


2.1、理论分析


我们继续使用上篇的数据库表,对于person和car两张表,person的cars和car的关系是一对多;而car的owner和person的关系是一对一。


当我们需要查询哪些车有主人,即哪些人有车时,就需要用到person left-join car;

注意:查询结果以car表为主,即未匹配成功的数据将会被None填充。另,car中owner无数据的将会被过滤掉。


2.1.1、原始表


person表:


# person表:
# 13  phyger-0  18  
# 14  phyger-1  18  
# 15  phyger-2  18  
# 16  phyger-3  18  
# 17  phyger-4  18  
# 18  phyger-5  18  
# 19  phyger-6  18  
# 20  phyger-7  18  
# 21  phyger-8  18  
# 22  phyger-9  18  
# 23  phyger-10 18
复制代码


car表:


# car表
# 1 byd 宋Pro-Dmi  NULL  
# 2 吉利  星越L     13  
# 3 哈佛  H6        13
复制代码


2.1.2、person left join car


# person  left-join  car  之后:
# p.id ---------------------------------- c.owner
# 13  phyger-0  18  1 byd 宋Pro-Dmi       NULL(x)
# 14  phyger-1  18  2 吉利  星越L          13  (√)  //和13匹配成功一条
# 15  phyger-2  18  3 哈佛  H6            13  (√)   //又和13匹配成功一条
# 16  phyger-3  18  
# 17  phyger-4  18  
# 18  phyger-5  18  
# 19  phyger-6  18  
# 20  phyger-7  18  
# 21  phyger-8  18  
# 22  phyger-9  18  
# 23  phyger-10 18
复制代码


2.1.3、p的id和c的owner匹配后


# on p.id==c.owner 匹配之后:
# p.id ---------------------------------- c.owner
# 13  phyger-0  18  2 吉利    星越L         13
# 13  phyger-0  18  2 哈佛    H6            13  
# 14  phyger-1  18  ↘ 全部None补全
# 15  phyger-2  18  
# 16  phyger-3  18  
# 17  phyger-4  18  
# 18  phyger-5  18  
# 19  phyger-6  18  
# 20  phyger-7  18  
# 21  phyger-8  18  
# 22  phyger-9  18  
# 23  phyger-10 18
复制代码


2.2、代码实现


首先,我们写一个函数去实现left-join。因为需要使用db_session去解决数据库的优雅连接问题,所以我们使用函数去做。


# left-join,结果以car表(左表)为主,结果的结构自己定义
@db_session
def lftj():
    '''
    @note: 左连接即将后表链接在前表的左边
    @code: left_join((p, c.name) for p in Person for c in p.cars)
         此段代码的意思是:
            将car表连接在person表的左边,当p的id等于c的owner时,匹配成功。(即找到有车的人)
    @对应的SQL:        
            SELECT "p", "c"."name"
            FROM "person" "p"
            LEFT JOIN "car" "c"
            ON "p"."id" = "c"."owner"
            GROUP BY "p"."id"
    '''
    for i in left_join((p, c.name) for p in Person for c in p.cars):
        print(i)
复制代码


以上代码的核心就是left_join((p, c.name) for p in Person for c in p.cars),首先这段代码的返回值是一个query对象,是可迭代的;其次,left_join的第一个参数就是结果表结构,即p对象和c的name两列;for p in Person就相当于FROM "person" "p",即从Person表查询,别名为p;for c in p.cars最重要,它表达的意思就是left join Car且ON "p"."id" = "c"."owner",最终返回一个query对象。


然后我们对这个query对象进行遍历打印。


代码运行结果:


网络异常,图片无法展示
|


这个查询结果表示,所有车有主人的是吉利和哈佛;而且吉利和哈佛的主人都是Person[13]。


对于这个结果表结构,我们可以在left-join的第一个参数中进行定义。


...
for i in left_join((p.name,p.age, c.name) for p in Person for c in p.cars):
        print(i)
复制代码


以上代码的执行结果:


网络异常,图片无法展示
|


2.3、去掉None


我想实际开发中,我们经常会需要将这些未匹配成功的数据过滤掉,当然我们可以通过left-join后进行过滤,但是这样就多了一步,值得高兴的是Pony的select就可以同时实现left-join和过滤None的效果。


# 联合查询,结果是交集,结果的结构自己定义
@db_session
def xx():
    for i in select((p.name,p.age, c.name) for p in Person for c in p.cars):
        print(i)
if __name__ == '__main__':
    db.generate_mapping(create_tables=True)
    xx()
复制代码


通过上述代码,我们可以看到select和left-join的语法完全一样,只是结果有区别。


代码执行结果:

网络异常,图片无法展示
|


3、最后


其实只要了解了left-join的原理,不论我们使用何种ORM框架,其底层SQL都是一致的。

相关文章
|
12月前
|
SQL
SAP CDS view 里 Inner Join,Left Outer Join 和 Right Outer Join 的区别
SAP CDS view 里 Inner Join,Left Outer Join 和 Right Outer Join 的区别
|
关系型数据库 MySQL
left join、right join和join,傻傻分不清?
真的是一张图道清所有join的区别啊,可惜我还是看不懂,可能人比较懒,然后基本一个left join给我就是够用的了,所以就没怎么去仔细研究了,但是现实还是逼我去搞清楚,索性自己动手,总算理解图中的含义了,下面就听我一一道来。
101 1
SQL外部联合:right outer join、left outer join、full outer join
SQL将外部联合分为了右外部联合(right outer join)、左外部联合(left outer join)、完全外部联合(full outer join)3个类型。
Inner Join与Left Join
Inner Join与Left Join
101 0
|
关系型数据库 MySQL
inner join 、left join、right join,优先使用inner join
inner join 、left join、right join,优先使用inner join
left join ... is null 的实际应用
left join ... is null 的实际应用
left join ... is null 的实际应用
|
关系型数据库 MySQL
八、inner join 、left join、right join,优先使用inner join
八、inner join 、left join、right join,优先使用inner join
320 0
|
SQL 关系型数据库 MySQL
Join,left join,right join(1)--连接原理(三十九)
Join,left join,right join(1)--连接原理(三十九)
|
SQL 语音技术 数据库
SQL基础【十五、join、Inner join、Left join、Right join、Full join】
SQL基础【十五、join、Inner join、Left join、Right join、Full join】
152 0
SQL基础【十五、join、Inner join、Left join、Right join、Full join】
Inner Join, Left Outer Join和Association的区别
测试用的CDS视图的源代码,第8行用Inner Join连接TJ02T, 后者存放了所有系统状态的ID和描述。
Inner Join, Left Outer Join和Association的区别