Python和MySQL对比(2):用Pandas 实现MySQL的 union 和 join 语法效果

news2024/11/15 13:23:54

文章目录

  • 一、前言
  • 二、语法对比
    • 数据表
    • union
    • join
      • 1、两表 inner join
      • 2、两表 left join
      • 3、两表 right join
      • 4、两表 outer join
      • 5、多表 join
  • 三、小结

一、前言

环境:
windows11 64位
Python3.9
MySQL8
pandas1.4.2

本文主要介绍 MySQL 中的unionjoin如何使用pandas实现,同时二者又有什么区别。

注:Python是很灵活的语言,达成同一个目标或有多种途径,我提供的只是其中一种解决方法,大家有其他的方法也欢迎留言讨论。

二、语法对比

数据表

本次使用的数据如下。
使用 Python 构建该数据集的语法如下:

import pandas as pd
import numpy as np

df1 = pd.DataFrame({ 'col1' : list(range(1,7))
                    ,'col2' : ['AA','AA','AA','BB','BB','BB']#list('AABCA')
                    ,'col3' : ['X',np.nan,'Da','Xi','Xa','xa']
                    ,'col4' : [10,5,3,5,2,None]
                    ,'col5' : [90,60,60,80,50,50]
                    ,'col6' : ['Abc','Abc','bbb','Cac','Abc','bbb']
                   })
df2 = pd.DataFrame({'col2':['AA','BB','CC'],'col7':[1,2,3],'col4':[5,6,7]})
df3 = pd.DataFrame({'col2':['AA','DD','CC'],'col8':[50,70,90]})

注:直接将代码放 jupyter 的 cell 跑即可。后文都直接使用df1df2df3调用对应的数据。

使用 MySQL 构建该数据集的语法如下:

with t1 as(
  select  1 as col1, 'AA' as col2, 'X' as col3, 10.0 as col4, 90 as col5, 'Abc' as col6 union all
  select  2 as col1, 'AA' as col2, null as col3, 5.0 as col4, 60 as col5, 'Abc' as col6 union all
  select  3 as col1, 'AA' as col2, 'Da' as col3, 3.0 as col4, 60 as col5, 'bbb' as col6 union all
  select  4 as col1, 'BB' as col2, 'Xi' as col3, 5.0 as col4, 80 as col5, 'Cac' as col6 union all
  select  5 as col1, 'BB' as col2, 'Xa' as col3, 2.0 as col4, 50 as col5, 'Abc' as col6 union all
  select  6 as col1, 'BB' as col2, 'xa' as col3, null as col4, 50 as col5, 'bbb' as col6 
)
,t2 as(
  select  'AA' as col2, 1 as col7, 5 as col4 union all
  select  'BB' as col2, 2 as col7, 6 as col4 union all
  select  'CC' as col2, 3 as col7, 7 as col4 
)
,t3 as(
  select  'AA' as col2, 50 as col8 union all
  select  'DD' as col2, 70 as col8 union all
  select  'CC' as col2, 90 as col8 
)
select * from t1;

注:直接将代码放 MySQL 代码运行框跑即可。后文跑 SQL 代码时,默认带上数据集(代码的1~18行),仅展示查询语句,如第9行。

对应关系如下:

Python 数据集MySQL 数据集
df1t1
df2t2
df3t3

union

union的情况比较简单,就分两种:不去重的union all和去重的union

1、不去重 union all
可以使用 Pandas 的pd.concat()函数实现 MySQL 的union
注意向pd.concat()函数传递一个列表,将所有的数据集作为列表的元素,如果有三个表单进行union,则给列表3个对应的数据集作为元素即可,有几个加几个。reset_index()函数是重置索引,而参数drop=True则是删除旧的索引,如果不删除则是会多加一列index。如果不需要重置索引,则可以将.reset_index(drop=True)去掉。

语言PythonMySQL
代码pd.concat([df1.col2,df2.col2]).reset_index(drop=True)select col2 from t1 union all select col2 from t2;
结果image.pngimage.png

union前后的表单有其他限制的时候,比如下例,则按照上一篇文章《Python和MySQL对比(1):用Pandas 实现MySQL语法效果》中的where条件进行处理即可。

语言PythonMySQL
代码df1_1 = df1.col2[df1.col2==‘BB’]
df2_1 = df2.col2[df2.col2==‘AA’]
pd.concat([df1_1, df2_1]).reset_index(drop=True)
select col2 from t1 where col2=‘BB’ union all select col2 from t2 where col2=‘AA’;
结果image.pngimage.png

2、去重 union
MySQL 使用union,不加all,实现对合并的数据表进行去重,在 Pandas 中可以使用df.drop_duplicates()实现同样的效果。

语言PythonMySQL
代码pd.concat([df1.col2,df2.col2]).drop_duplicates().reset_index(drop=True)select col2 from t1 union
select col2 from t2;
结果image.pngimage.png

join

join的内容比较多,分inner joinleft joinright joinouter join。在 Pandas 中,一般使用merge()实现,另外 Pandas 还有一个生成笛卡尔积的cross join,不过一般不会用到。用的最多的还是两个基本的inner joinleft joinleft join的联结方式相对比较好理解一些,right join一般可以通过left join实现。
而这些联结方式中,又分单个条件(on)和多个条件(and)、两个表的关联和多个表的关联。
下文就分别通过两个表介绍四种联结方法(顺带介绍多条件)和使用inner joinleft join进行多表关联展开叙述。

1、两表 inner join

单条件,一般只有**on****将两个表的一个外键进行关联。**当两个表的键相同的时候,可以使用【代码一】直接使用on;如果两个表的键不同,则可以使用【代码二】分别用left_onright_on指定对应的键的名称。suffixes参数是传递两个后缀,当两个表除了关联的外键之外,有同名的字段的时候,则分别给两个表同名的字段加上这里指定的后缀,默认是('_x','_y'),即左表的同名字段加上_x后缀,右表的同名字段加上_y后缀。
【代码一】和【代码二】都是使用pd.merge(df1,df2)进行操作,该函数的第一个参数是left即左表,第二个参数是right即右表;除了使用该方式,也可以使用df1.merge(df2)df1是左表,df2是右表,其他的参数和上一小段讲的一致。如下【代码三】和【代码四】的示例。
注:由于 MySQL 联结之后,有两个相同的列,第一个列的数据会被第二个列的数据覆盖,所以看到两个col2col4列,且数据一致。而 Pandas 会将键保留一个,其他同名列加上后缀区分。

语言PythonMySQL
代码【代码一】pd.merge(df1,df2,on=‘col2’,how=‘inner’,suffixes=(‘_left’,‘_right’))
【代码二】pd.merge(df1,df2,left_on=‘col2’,right_on=‘col2’,how=‘inner’,suffixes=(‘_left’,‘_right’))
【代码三】
df1.merge(df2,on=‘col2’,how=‘inner’,suffixes=(‘_left’,‘_right’))
【代码四】
df1.merge(df2,left_on=‘col2’,right_on=‘col2’,how=‘inner’,suffixes=(‘_left’,‘_right’))
select *
from t1
join t2 on t1.col2=t2.col2 ;
结果image.png
image.png
image.png
image.png
image.png

多条件-多个键
当多个键联结时,在单个键的基础上修改一下onleft joinright join的参数即可,以列表的形式作为参数值,列表的每个元素是外键的名称,每个外键在列表中的索引位置必须一一对应。
注:单个建,也可以使用列表的形式,传递键,这时列表中只有一个元素。

语言PythonMySQL
代码【代码一】
pd.merge(df1,df2,left_on=[‘col2’,‘col4’],right_on=[‘col2’,‘col4’],how=‘inner’,suffixes=(‘_left’,‘_right’))
【代码二】
pd.merge(df1,df2,on=[‘col2’,‘col4’],how=‘inner’,suffixes=(‘_left’,‘_right’))
【代码三】
df1.merge(df2,left_on=[‘col2’,‘col4’],right_on=[‘col2’,‘col4’],how=‘inner’,suffixes=(‘_left’,‘_right’))
【代码四】
df1.merge(df2,on=[‘col2’,‘col4’],how=‘inner’,suffixes=(‘_left’,‘_right’))
select * from t1 join t2 on t1.col2=t2.col2 and t1.col4=t2.col4;
结果image.png
image.png
image.png
image.png
image.png

多条件-单表限制条件
以下4个代码返回的结果是一致的。
针对 MySQL 的两个代码,【MySQL1】是join时同时进行筛选,而【MySQL2】则是先join完再进行where
使用 pandas 实现的时候,可以在merge()前进行条件筛选,如下【代码一】;也可以在merge()之后再进行条件筛选,如下【代码二】。
注:用df1.merge(df2)pd.merge(df1,df2)大同小异,针对df1.merge(df2)不再赘述。

语言PythonMySQL
代码【代码一】
pd.merge(df1,df2[df2.col2==‘AA’],left_on=[‘col2’],right_on=[‘col2’],how=‘inner’,suffixes=(‘_left’,‘_right’))
【代码二】
df1_1 = pd.merge(df1,df2,left_on=[‘col2’],right_on=[‘col2’],how=‘inner’,suffixes=(‘_left’,‘_right’))
df1_1[df1_1.col2==‘AA’]
【MySQL1】
select *
from t1
join t2 on t1.col2=t2.col2
and t2.col2=‘AA’;
【MySQL2】
select *
from t1
join t2 on t1.col2=t2.col2
where t2.col2=‘AA’;
结果image.png
image.png
image.png

2、两表 left join

多条件-多键
单条件的比较简单,直接看一个多键的情况。
用 Python 实现left join的语法和inner join的语法差不多,只是把how的参数由inner改为left即可。当然,返回的结果是有一定差别的。left join是以左表为准,将右表能通过外键关联上的字段关联到左表上。
差异:在下面的例子中可以看出一些差异,Python 返回的结果只保留了左表的键,如果需要使用到右表的键,则不能直接使用,需要借助右表其他的列辅助判断。而 MySQL 还是可以通过 t2.col2t2.col4进行调用右表的键。

语言PythonMySQL
代码pd.merge(df1,df2,left_on=[‘col2’,‘col4’],right_on=[‘col2’,‘col4’],how=‘left’,suffixes=(‘_left’,‘_right’))select * from t1 left join t2 on t1.col2=t2.col2 and t1.col4=t2.col4;
结果image.pngimage.png
注:截图中由于有相同列,导致相同列显示数据不准确。

多条件-单表限制条件
当有多条件,且是对单独的表单进行限制的时候,和inner join有一些差异,下图是前面inner join多条件-单表限制条件的4个代码,结果是一致的。
如果改为left join,结果会大不同。
image.png
如下,【MySQL1】和【MySQL2】结果有很大不同,【MySQL1】是以t1为主表,and t2.col2='AA'条件是在关联的时候对t2进行筛选,筛选完再将t2关联到t1上,所以返回的记录都有t1表的数据,再加上能关联上t1.col2t2表的列数据。而【MySQL2】是以t1为主表,直接将t2关联到t1上,然后再对关联后的数据通过where t2.col2='AA'进行筛选。
Python 【代码一】效果同【MySQL1】,【代码二】效果同【MySQL2】。

语言PythonMySQL
代码【代码一】
pd.merge(df1,df2[df2.col2==‘AA’],left_on=[‘col2’],right_on=[‘col2’],how=‘left’,suffixes=(‘_left’,‘_right’))
【代码二】
df1_1 = pd.merge(df1,df2,left_on=[‘col2’],right_on=[‘col2’],how=‘left’,suffixes=(‘_left’,‘_right’))
df1_1[df1_1.col2==‘AA’]
【MySQL1】
select * from t1
left join t2 on t1.col2=t2.col2
and t2.col2=‘AA’;
【MySQL2】
select * from t1
left join t2 on t1.col2=t2.col2
where t2.col2=‘AA’;
结果image.png
image.png
image.png
image.png

3、两表 right join

right joinleft join语法和含义上差不多,如果将左右表位置换一下,就可以通过right join替换left join,具体看看下面例子,和left join的【多条件-多键】的效果(下图)是一致的。
image.png
从以下例子可以看出二者的一些差异,Python 返回的结果只保留了右表的键,如果需要使用到左表的键,则不能直接使用,需要借助左表其他的列辅助判断。而 MySQL 还是可以通过 t2.col2t2.col4进行调用左表的键。

语言PythonMySQL
代码pd.merge(df2,df1,left_on=[‘col2’,‘col4’],right_on=[‘col2’,‘col4’],how=‘right’,suffixes=(‘_left’,‘_right’))select * from t1 left join t2 on t1.col2=t2.col2 and t1.col4=t2.col4;
结果image.pngimage.png
注:截图中由于有相同列,导致相同列显示数据不准确。

4、两表 outer join

outer join也叫full join,在 MySQL 8 中,有一些版本不支持full join,下表的【MySQL1】使用了full join的方式进行关联,如果使用不了该语法,也可以使用【MySQL2】或【MySQL3】代替。(注意,由于有多列col2,第一列会被第二列覆盖,所以为了看出差异,可以对其中一列进行重命名。)
而在 Python 中,没有对outer join限制,可以一步到位,如下【代码一】,该结果和 MySQL 也有一定的差异,主要是 Python 代码对左右表的col2列进行了合并,所以看到的col2列有4个值。另外, Python 的【代码二】和【代码三】也可以实现一样的效果,逻辑和【MySQL2】和【MySQL3】类似,不过由于外键覆盖,使用不到右表的外键,所以【代码三】通过右表的其他字段将空值筛选掉,但是需要保证这个其他字段没有空值,否则会使得原本需要保留的空值也被剔除掉。

语言PythonMySQL
代码【代码一】
pd.merge(df2,df3,left_on=[‘col2’],right_on=[‘col2’],how=‘outer’,suffixes=(‘_left’,‘_right’))
【代码二】
df2_1 = pd.merge(df2,df3,left_on=[‘col2’],right_on=[‘col2’],how=‘left’,suffixes=(‘_left’,‘_right’))
df3_1 = pd.merge(df2,df3,left_on=[‘col2’],right_on=[‘col2’],how=‘right’,suffixes=(‘_left’,‘_right’))
pd.concat([df2_1, df3_1]).drop_duplicates().reset_index(drop=True) # 推荐
【代码三】
df2_1 = pd.merge(df2,df3,left_on=[‘col2’],right_on=[‘col2’],how=‘left’,suffixes=(‘_left’,‘_right’))
df3_1 = pd.merge(df2,df3,left_on=[‘col2’],right_on=[‘col2’],how=‘right’,suffixes=(‘_left’,‘_right’))
pd.concat([df2_1, df3_1[df3_1.col4.isna()]]).reset_index(drop=True) # 如果df3_1.col4本身有空值,会影响最终结果
【MySQL1】
select * from t2 full join t3 on t3.col2=t2.col2;
【MySQL2】
select * from t2 left join t3 on t3.col2=t2.col2
union all
select * from t3 left join t2 on t3.col2=t2.col2 where t2.col2 is null;
【MySQL3】
select * from t2 left join t3 on t3.col2=t2.col2
union all
select * from t2 right join t3 on t3.col2=t2.col2 where t2.col2 is null;
结果image.pngimage.png
注:由于有多个相同列,第一列的数据会被第二列覆盖,可以通过命别名形式避免该问题。

其实,本次结果应该如下图所示。MySQL 和 Python 由于一些限制,返回的结果都有一些出入。
image.png
该图的 MySQL 代码如下:

select t2.col2 t2_col2,t2.col7,t2.col4,t3.col2 t3_col2,t3.col8 
from t2 full join t3 on t3.col2=t2.col2;
-- 或
select t2.col2 t2_col2,t2.col7,t2.col4,t3.col2 t3_col2,t3.col8
from t2 left join t3 on t3.col2=t2.col2
union all
select t2.col2 t2_col2,t2.col7,t2.col4,t3.col2 t3_col2,t3.col8
from t3 left join t2 on t3.col2=t2.col2 where t2.col2 is null;

5、多表 join

多表进行join的时候,推荐使用df1.merge(df2)的形式来进行链式join,如下例子

语言PythonMySQL
代码df1.merge(df2,left_on=‘col2’,right_on=‘col2’,how=‘left’).merge(df3,left_on=‘col2’,right_on=‘col2’,how=‘left’)
select * from t1 left join t2 on t2.col2=t1.col2 left join t3 on t3.col2=t1.col2
结果image.pngimage.png
注:由于有多个相同列,第一列的数据会被第二列覆盖,可以通过命别名形式避免该问题。

Python 对外键的处理同样存在合并的情况,除了该问题,还需要注意的一点是,当非外键有重复列的时候,Python 会添加后缀,如果后缀在后面的join中有作为外键使用,则需要注意加上带有外键的字段名称。

语言PythonMySQL
代码df1.merge(df2,left_on=‘col2’,right_on=‘col2’,how=‘left’,suffixes=(‘_x’,‘_y’)).merge(df3,left_on=‘col4_y’,right_on=‘col8’,how=‘left’,suffixes=(‘_left’,‘_right’))
select * from t1 left join t2 on t2.col2=t1.col2 left join t3 on t3.col8=t2.col4;
结果image.pngimage.png
注:由于有多个相同列,第一列的数据会被第二列覆盖,可以通过命别名形式避免该问题。

三、小结

Python 在多表联结的时候,会对外键进行合并,当使用的是inner join时,无所谓,但是如果使用的是left joinright joininner join时,需要注意该差异,避免一些不必要的错误。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/130941.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring 核心概念 IOC/DI IOC容器 Bean

目录 一:代码书写现状 二:核心思想 一:代码书写现状 常规操作如上,但存在着问题,将项目上线后,需要将数据层进行更换,更换如下: 数据层更换后,业务层也需要进行更换,更换如下: 数据…

NLP学习笔记(五) 注意力机制

大家好,我是半虹,这篇文章来讲注意力机制 (Attention Mechanism) 在序列到序列模型中的应用 在上一篇文章中,我们介绍了序列到序列模型,其工作流程可以概括为以下两个步骤 首先,用编码器将输入序列编码成上下文向量&a…

费控产品之易快报洞察解析

1.费控行业洞察 1.1 概念及管理范畴界定 费控业务的本质是企业支出的管理,因此分析费控要从企业支出管理的宏观范畴来看,企业支出主要包括两方面,一个是企业成本,一个是期间费用。期间费用就是我们常说的管理费用、销售费用和财务…

Centos7的安装与模板机的制作

Centos7的安装与模板机的制作 1.安装环境准备 1.VMware Workstation 2.centos7镜像 本文用的VMware版本为16.2.1 build-18811642 2.开始安装 话不多说,直接上图 3.模板机制作 1.查看防火墙的运行状态 firewall-cmd --state防火墙目前正在启动中 2.关闭防火墙…

STM32——STM32简介与创建工程

文章目录一、stm32简介stm32MCU:ARM:命名规则:片上资源/外设:系统结构:引脚的定义功能引脚介绍:最小系统引脚介绍:电源引脚介绍:启动配置最小系统电路二、软件安装三、新建工程固件库…

2022年专业408的算法题

文章目录0 结果1 题目2 思路3 实现3.1 思路13.2 思路二0 结果 1 题目 2 思路 1,首先明确二叉搜索树的定义:任何一个节点大于其左子树中的全部结点,小于其右子树中的全部结点。中序遍历二叉搜索树得到一个升序序列。2,明确题目中给…

【微信小程序入门到精通】— 微信小程序实现多页面切换(tabBar)

目录前言一、tabBar 介绍二、实操(创建 tabBar )2.1 基本配置2.2 详细配置总结前言 对于目前形式,微信小程序是一个热门,那么我们该如何去学习并且掌握之后去做实际项目呢? 为此我特意开设此专栏,在我学习的…

mysql索引机制实现及自适应hash索引

一、介绍   哈希(hash)是一种非常快的查找方法,一般情况下查找的时间复杂度为O(1)。常用于连接(join)操作,如Oracle中的哈希连接(hash join)。 InnoDB存储…

canopen11-sdo-40读取命令

源码 参考文件 1、SDO介绍 就对象而言,主机要访问节点词典的数据,因此主机是client客户端,节点是server服务器。上传与下载是对服务器来说的(这点和常识有点不太一样)。因此,上传指的是服务器发送数据给客户端,下载是客户端给服务器数据。 我们这里要用主机访问节点服…

Linux多进程编程之exec函数族使用

Linux多进程编程之exec函数族使用1.exec函数族是什么2.execl函数具体使用3.execlp4.exec后面不同字母所代表的含义1.exec函数族是什么 顾名思义,它并不只是一个函数,而是以exec开头的六个函数,并且是没有exec这个函数的(就像TCP/…

几行代码演示linux kernel、libc、userSpace app的关系

问一:编译出来的Linux内核镜像(".\build\arch\arm64\boot\Image"),可以单独运行吗?答案是能,但是加载完就提示panic,然后死掉了。 原因是: 内核代码加载完后,一定要切换到低权限模式…

Wireshark TS | Packet Challenge 之 HTTP 案例分析

前言 来自于 Sharkfest Packet Challenge 中的一个数据包案例,Sharkfest 是 Wireshark 官方组织的一年一度的大会,致力于在 Wireshark 开发人员和用户社区之间分享知识、经验和最佳实践。印象中早期是一年一次,近几年发展成一年两次&#xf…

我的2022年终总结

目录 1 序 1 2 工作 1 3 业余 1 3.1 AI 1 3.2 数学小插曲 3 3.3 金融投资 3 4 生活 4 5 最后 4 1 序 老婆大人每年这个时候都要写年终总结,现在也正在写;CSDN也发起了年终征文活动;各大app也各种年度大数据总结。我好像还是第一次写年终总…

两两交换链表中的节点 -- 虚拟头节点

24两两交换链表中的节点 – 虚拟头节点 通过本题可以: 增加对虚拟头节点的理解。 加强对链表这一基本数据结构的基本操作的理解。 1. 交换过程: 如图,假设链表如图所示。 为了减少对头节点的单独讨论,这里采用虚拟头节点进行…

Allegro如何显示走线和铜皮的网络名操作指导

Allegro如何显示走线和铜皮的网络名操作指导 在做PCB设计的时候,如果可以实时看到走线和铜皮的网络名,对于设计有很大帮助,如下图 具体操作如下 选择Set-up-user preferences选择Display

Vue 总结一(简介 基本语法)

目录 Vue 是什么 与其它 JS 框架的关联 Vue 周边库 MVVM模型 怎么用 Vue模板语法有2大类: 数据绑定 data 事件 v-on methods 计算属性 computed 监视属性 watch computed和watch之间的区别: 条件渲染 v-if v-show Vue 是什么 一个动态构建用…

sql根据团队树一级一级汇总统计

1、需求描述 最近碰到了一个需求,是要统计各个团队的员工的销售金额,然后一级一级向上汇总。 架构团队树是类似于这种样子的,需要先算出每个员工的销售金额,然后汇总成上一级的团队金额,然后各个团队的销售总金额再往上…

京东技术发展简史

文章目录前言京东发展历程京东商城技术的演进京东自研技术分布式数据库StarDB京东云移动端Flutter在京东的实践大数据咚咚架构ShardingSphere京东人物参考“京东可以高速发展到今天的规模的原因,其中最核心的是坚持“倒三角”战略:建立出色的团队&#x…

转义字符与strlen(),sizeof()在一起的注意事项

转义字符与strlen(),sizeof() 1. 转义字符每个人都知道是怎么一回事儿,转义字符顾名思义就是转变意思。 2. 首先转义字符肯定是一个字符,不是两个字符,更不用说是数字了,就是字符。 3. 当用strlen()统计字符串长度时或者用sizeo…

2022年度回顾

这一年是不平凡的一年,换了公司,新公司频繁出差,去了临沂,去了河南,去了唐山,去了福鼎,当中最印象深刻的还是河南,项目万分火急,在疫情隔绝的10月份毅然决然的前往河南安…