Python和MySQL对比(3):用Pandas 实现MySQL的子查询、like_regexp、case when_if语法效果

news2025/1/16 5:46:15

文章目录

  • 一、前言
  • 二、语法对比
    • 数据表
    • 子查询
    • like/regexp
    • case when/if
    • in
  • 三、小结

一、前言

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

本文主要介绍 MySQL 中的子查询、like/regexp、case when/if 如何使用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

子查询

MySQL 的子查询常见的有4种类型,分别是在select中使用子查询、在from中使用子查询、在join中使用子查询、在in中使用子查询。

1、在select/join中使用子查询
以下代码中,【MySQL1】就是在select中使用了子查询,其语法的逻辑和【MySQL2】差不多。在join中使用子查询,就是将表名更换为一个 MySQL 查询语句。二者返回的结果一样。
需要注意的是在select中的子查询,只能返回一个字段,一般是聚合字段(如下表中的 MySQL 代码),如果是非聚合,外键必须要唯一,保证不发散(如下代码),否则会报错。

-- 由于t2表的外键都只有唯一一行,可以使用t2表中的字段col4或col7
select t1.col2,(select col4 from t2 where t2.col2=t1.col2) col9 
from t1;

select中使用子查询的方法,在 Python 中,只能通过拆分为普通的left join来实现。下面的 Python 代码分别根据agg()size()apply()三个函数实现和两个 MySQL 代码一样的效果。fillna()针对 DataFrame 对空值进行填空的时候,可以传入一个字典,键为列名,值为填充值,通过键值对填充指定列的空值。

语言PythonMySQL
代码【代码一:agg】
df1_1 = df1.groupby(‘col2’).agg({“col2”: ‘count’}).rename(columns={‘col2’:‘col9’}).reset_index()
df2.merge(df1_1,left_on=[‘col2’],right_on=[‘col2’],how=‘left’)[[‘col2’,‘col9’]].fillna({‘col9’:0})
【代码二:size】
df1_1 = df1.groupby(‘col2’).size().reset_index().rename(columns={0:‘col9’})
df2.merge(df1_1,left_on=[‘col2’],right_on=[‘col2’],how=‘left’)[[‘col2’,‘col9’]].fillna({‘col9’:0})
【代码三:apply】
df1_1 = df1.groupby(‘col2’).apply(lambda x:len(x)).reset_index().rename(columns={0:‘col9’})
df2.merge(df1_1,left_on=[‘col2’],right_on=[‘col2’],how=‘left’)[[‘col2’,‘col9’]].fillna({‘col9’:0})
【MySQL1】
select t2.col2,(select count() from t1 where t1.col2=t2.col2) col9 from t2;
【MySQL2】
select t2.col2,ifnull(t1.col9,0)col9 from t2 left join(select col2,count(
) col9 from t1 group by col2)t1 on t1.col2=t2.col2;
结果image.pngimage.png

2、在from中使用子查询
from中使用子查询,和join类似,就是将表名更换为一个 MySQL 查询语句。下面用from子查询实现【1、在select/join中使用子查询】中的查询结果。
相关的 Python 代码可参考【1、在select/join中使用子查询】中的三个 Python 代码。

语言PythonMySQL
代码【代码一:agg】
df1_1 = df1.groupby(‘col2’).agg({“col2”: ‘count’}).rename(columns={‘col2’:‘col9’}).reset_index()
df2.merge(df1_1,left_on=[‘col2’],right_on=[‘col2’],how=‘left’)[[‘col2’,‘col9’]].fillna({‘col9’:0})
select t2.col2,ifnull(t1.col9,0)col9 from(select col2,count(*) col9 from t1 group by col2) t1 right join t2 on t2.col2=t1.col2;
结果image.pngimage.png

3、在in中使用子查询
in中使用子查询,如【MySQL1】,子查询返回的col2字段作为目标值,对t1.col2进行筛选,并返回符合要求的数据。
在 Python 中,可以使用df2[df2.col7==2]实现子查询的功能,然后和df1表进行联结,最终指定返回的列。suffixes=('','_right')设置左表的后缀是空字符,即保留原来的列名,这样可以不用再使用rename()进行重命名。

语言PythonMySQL
代码df1.merge(df2[df2.col7==2],left_on=[‘col2’],right_on=[‘col2’],how=‘inner’,suffixes=(‘’,‘_right’))[[‘col1’,‘col2’,‘col3’,‘col4’,‘col5’,‘col6’]]【MySQL1】
select * from t1 where t1.col2 in(select col2 from t2 where col7=2);
【MySQL2】
select t1.* from t1 join t2 on t2.col2=t1.col2 where t2.col7=2;
结果image.pngimage.png

like/regexp

在 MySQL 中,对文本搜索匹配可以使用 like或者regexp。相比较之下,regexp的功能更强大,可以覆盖like匹配,like常见匹配和对应的regexp实现如下:

likeregexp说明
like ‘a%’regexp ‘^a’匹配以 a 开头的字符串
like ‘%a’regexp ‘a$’匹配以 a 结尾的字符串
like ‘%a%’regexp ‘a’匹配包含 a 的字符串
like ‘a_b’regexp ‘a.{1}b’匹配 a 和 b 之间只有一个字符的字符串

下面 MySQL 的示例只取上面的一种语法进行展示,需要尝试另外一种方式的小伙伴自行在本地测试。

在 Pandas 中,能实现以上功能的语法是.str.contains()。该方法也会一个正则匹配,所以可以用上表的regexp的匹配语法实现相关功能。
但是有一点需要注意,需要非空值,如果列有空值,使用.str.contains()会报错,所以在使用前可以先填充空值,随意填充一个不会被匹配到的字符即可;当然,由于不需要取到空值,直接剔除空值之后再执行匹配也是一种有效的处理方法。
根据上表4个语法分别展开来看看。

1、匹配以 a 开头的字符串
注意:MySQL 中没有区分大小写,所以【MySQL1】和【MySQL2】的效果是一样的。但是在 Pandas 中区分大小写,所以,下面的【代码一】使用的是大写的A,由于使用的数据表都是大写的A所以结果一致,当Aa混合时,不管使用A还是a,都便只能查出一部分值;为了能把所有值都查出来,可以做一步转化,如【代码二】,将字段都转化为小写,然后再进行匹配,如果你想转化为大写再匹配也是可以的,将lower()改为upper(),然后后面把a改为A即可(可参考【代码三】第二行代码)。
【代码一】和【代码二】都是使用fillna('')给空值填上空字符串,如果事先把空值剔除再进行匹配,可以参考【代码三】,先将去除空值后的数据集赋值给新的变量,然后使用新的变量进行upper()contains()

语言PythonMySQL
代码【代码一】
df1[df1.col6.fillna(‘’).str.contains(‘^A’)]
【代码二】
df1[df1.col6.fillna(‘’).str.lower().str.contains(‘^a’)]
【代码三】
df1_1 = df1[~df1.col6.isna()]
df1_1[df1_1.col6.str.upper().str.contains(‘^A’)]
【MySQL1】
select * from t1 where t1.col6 like’A%‘;
【MySQL2】
select * from t1 where t1.col6 like’a%’;
结果image.pngimage.png

2、匹配以 c 结尾的字符串

语言PythonMySQL
代码【代码一】
df1[df1.col6.fillna(‘’).str.lower().str.contains(‘c ′ ) ] < b r / > 【代码二】 < b r / > d f 1 1 = d f 1 [   d f 1. c o l 6. i s n a ( ) ] < b r / > d f 1 1 [ d f 1 1 . c o l 6. s t r . u p p e r ( ) . s t r . c o n t a i n s ( ′ C ')]<br />【代码二】<br />df1_1 = df1[~df1.col6.isna()]<br />df1_1[df1_1.col6.str.upper().str.contains('C )]<br/>【代码二】<br/>df11=df1[ df1.col6.isna()]<br/>df11[df11.col6.str.upper().str.contains(C’)]
select * from t1 where t1.col6 like’%c’;
结果image.pngimage.png

3、匹配包含 a 的字符串

语言PythonMySQL
代码【代码一】
df1[df1.col6.fillna(‘’).str.lower().str.contains(‘a’)]
【代码二】
df1_1 = df1[~df1.col6.isna()]
df1_1[df1_1.col6.str.upper().str.contains(‘A’)]
select * from t1 where t1.col6 like’%a%’
结果image.pngimage.png

4、匹配 a 和 c 之间只有一个字符的字符串

语言PythonMySQL
代码【代码一】
df1[df1.col6.fillna(‘’).str.lower().str.contains(‘a.{1}c’)]
【代码二】
df1_1 = df1[~df1.col6.isna()]
df1_1[df1_1.col6.str.upper().str.contains(‘A.{1}C’)]
select * from t1 where t1.col6 like’a_c’;
结果image.pngimage.png

注:关于正则,可以参考我过往发布的一篇文章《Python 进阶:正则表达式》,基本语法大同小异。

case when/if

MySQL 的case whenif都是用于对某列字段进行条件判断,处理完返回新的列,二者也可以进行互换,一般if用于单条件的判断,case when用于多条件的判断。
在 Python 中,可以用map()加上一个函数,或使用numpy.select()实现相关的功能。

1、单条件
【MySQL1】和【MySQL2】跑出来的结果一样。
为了不改变源表,Python 代码都赋值给一个新的变量,不在源表上进行操作。
通过 Python 实现【MySQL1】的效果有多种方案,可以通过map()+一个函数,这个函数可以是用lambda写的匿名函数,也可以使用def func()定义的函数,如下【代码一】、【代码二】;也可以使用apply()替换map(),如【代码三】(对比【代码一】,也可以对【代码二】替换map()apply()实现。);另外,在 Numpy 中,还有一个select()函数可以实现相同的效果,如【代码四】。
注:【代码一】、【代码二】、【代码三】、【代码四】运行完结果都一致。

语言PythonMySQL
代码【代码一】
df1_1 = df1.copy()
df1_1[‘等级’] = df1_1.col5.map(lambda x: ‘及格’ if x >= 60 else ‘不及格’ );
df1_1[[“col2”,“等级”]]
【代码二】
def func(x):
if x >= 60:
return ‘及格’
else:
return ‘不及格’
df1_1=df1.copy()
df1_1[‘等级’] = df1_1.col5.map(func)
df1_1[[“col2”,“等级”]]
【代码三】
df1_1 = df1.copy()
df1_1[‘等级’] = df1_1.col5.apply(lambda x: ‘及格’ if x >= 60 else ‘不及格’ );
df1_1[[“col2”,“等级”]]
【代码四】
df1_1 = df1.copy()
conditions = [df1_1.col5>=60, df1_1.col5<60]
choices = [‘及格’, ‘不及格’]
df1_1[‘等级’] = np.select(conditions, choices)
df1_1[[“col2”,“等级”]]
【MySQL1】
select col2,(case when col5 >= 60 then ‘及格’ else ‘不及格’ end) as “等级” from t1;
【MySQL2】
select col2,if(col5 >= 60,‘及格’,‘不及格’) as “等级” from t1;
结果image.pngimage.png

2、多条件
多条件和单条件大同小异,【MySQL11】使用case when在原有的基础上多加了一个when…then…条件分支,【MySQL2】使用if()则需要多加一层嵌套。
在 Python 中,如【代码一】使用map()+lambda,需要多嵌套一层if函数,而【代码二】使用apply()+func()多加一个elif分支;最后【代码三】使用numpy.select()则在两个列表对应的位置,加上对应的条件即可。
需要注意的是,当列中有null值的时候,Python 的【代码一】和【代码二】由于和 MySQL 一样都使用其他的所有情况都视为不及格,所以直接把null值处理为不及格,但是【代码三】并没有对null值做处理,所以会返回0。处理方法很简单,再加一个条件即可,代码对比示例如下:

# 未处理null值,“等级”字段返回0
df1_1 = df1.copy()
conditions = [df1_1.col4>=9,df1_1.col4>=5, df1_1.col4<5 ]
choices = ['优秀','及格', '不及格']
df1_1['等级'] = np.select(conditions, choices)
df1_1[["col2","等级"]]

# null值处理为“不及格”
df1_1 = df1.copy()
conditions = [df1_1.col4>=9,df1_1.col4>=5, df1_1.col4<5 , df1_1.col4.isna()]
choices = ['优秀','及格', '不及格', '不及格']
df1_1['等级'] = np.select(conditions, choices)
df1_1[["col2","等级"]]
语言PythonMySQL
代码【代码一】
df1_1 = df1.copy()
df1_1[‘等级’] = df1_1.col5.map(lambda x: ‘优秀’ if x >= 85 else(‘及格’ if x >= 60 else ‘不及格’ ))
df1_1[[“col2”,“等级”]]
【代码二】
def func(x):
if x >= 85:
return ‘优秀’
elif x >= 60:
return ‘及格’
else:
return ‘不及格’
df1_1=df1.copy()
df1_1[‘等级’] = df1_1.col5.apply(func)
df1_1[[“col2”,“等级”]]
【代码三】
df1_1 = df1.copy()
conditions = [df1_1.col5>=85,df1_1.col5>=60, df1_1.col5<60]
choices = [‘优秀’,‘及格’, ‘不及格’]
df1_1[‘等级’] = np.select(conditions, choices)
df1_1[[“col2”,“等级”]]
【MySQL1】
select col2,(case when col5 >= 85 then ‘优秀’ when col5 >=60 then ‘及格’ else ‘不及格’ end) as “等级” from t1;
【MySQL2】
select col2,if(col5 >=85,‘优秀’,if(col5 >=60,‘及格’,‘不及格’)) as “等级” from t1;
结果image.pngimage.png

in

MySQL 中的in语法比较简单,在 Pandas 中使用isin()便可实现相关功能。

语言PythonMySQL
代码pd.Series(df1.col2.unique())select distinct col2 from t1;
结果image.pngimage.png

三、小结

Python 在实现子查询时,其实就是通过赋值给一个新的变量,然后使用新的变量再进行merge(),当然,也可以不用赋值新的变量,直接作为左表或右表的参数值进行传递。
Python 在实现like/regexp时,则是通过.str.contains(),使用正则进行匹配,需要注意的是空值的填充。
Python 在实现case when/if时,则是使用函数,可以是lambda匿名函数,也可以是通过def function()定义的函数。

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

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

相关文章

FPGA中二进制数的运算

一、B比特的二进制数可以表示的范围 无符号整数&#xff1a;0~2B-1 有符号整数&#xff1a;-2B-1~2B-1-1 二、有符号数&#xff08;补码&#xff09;与十进制数之间的转换 D&#xff1a;十进制数 B&#xff1a;二进制数aB-1aB-2a1a0的位数 aB-1:符号位 三、符号位拓展 在使…

Android 12 蓝牙适配 Java版

Android 12.0蓝牙适配前言正文一、Android版本中蓝牙简介二、新建项目① 配置build.gradle② 配置AndroidManifest.xml三、打开蓝牙① 打开蓝牙意图② 请求BLUETOOTH_CONNECT权限意图四、蓝牙扫描① 扫描者② 扫描回调③ 扫描方法④ 执行扫描⑤ 应用不推导物理位置五、页面显示…

基于Java+Springboot+vue体育用品销售商城平台设计和实现

基于JavaSpringbootvue体育用品销售商城平台设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取…

Docker部署JAVA项目

一、 Docker安装 1、yum 包更新到最新 yum update 2、安装需要的软件包&#xff0c; yum-util 提供yum-config-manager功能&#xff0c;另外两个是devicemapper驱动依赖的 yum install yum-utils device-mapper-persistent-data lvm2 -y 3、 设置yum源 yum-config-manage…

等级保护----1、网络安全等级保护一级安全测评要求

文章目录一、安全测评通用要求1、安全物理环境1.1 物理访问控制1.2 防盗窃和防破坏1.3 防雷击1.4 防火1.5 防水和防潮1.6 温湿度控制1.7 电力供应2、安全通信网络2.1 通信传输2.2 可信验证3、安全区域边界3.1 边界防护3.2 访问控制3.3 可信验证4、安全计算环境4.1 身份鉴别4.2 …

使用关键字like进行模糊查询

【模糊查询】&#xff1a;使用关键字like [支持%或者下划线匹配&#xff0c;%匹配任意多个字符&#xff0c;一个下划线只匹配任意一个字符。] 实例&#xff1a; 查询名字中带有字母o的员工&#xff1a; select * from emp where ename like %o%; 找出名字以T结…

2000-2021.3月土地交易高频数据库(含爬取代码和数据)

2000-2021.3月土地交易高频数据库&#xff08;含爬取代码和数据&#xff09; 1、时间跨度&#xff1a;2000-2021年3月1日 2、指标&#xff1a;年份、电子监管号、所在省份、所在城市、所在区县、经度、纬度、项目名称、项目位置、面积、土地来源、土地用途、供地方式、土地使…

Python CV 实现风格化图片转换

前几天遇到一个风格化图片转换的需求&#xff0c;效果像这样&#xff1a; 像这样&#xff0c;需要用纯色圆形填充图像&#xff0c;形成风格化的图片样式。 实现原理 整体原理还是比较简单的&#xff0c;有点类似与马赛克的处理方式。 假设图片宽 w 像素&#xff0c;高 h 像素…

FLStudio21中文版下载及水果软件2023功能介绍

如今&#xff0c;越来越多的音乐人选择使用音乐制作软件来进行音乐的创作&#xff0c;一台电脑、一款软件以及一个外接MIDI就是一个小型的音乐工作站&#xff0c;而如今非常流行的FL Studio&#xff08;在国内被称为“水果”&#xff09;成了音乐界无论萌新还是大佬们的首选&am…

二阶微分算子与反锐化屏蔽

二阶微分算子 任意二阶微分必须满足&#xff1a;灰度不变的区域微分值为0&#xff1b;灰度台阶或斜坡的起点处微分值非0&#xff1b;沿着斜坡的微分值为0。由于处理离散值&#xff0c;因此微分用差分近似&#xff1a; 二维图像f(x,y),沿着两个空间坐标轴求解二阶微分&#xff1…

逆向-还原代码之little-or-big (Arm 64)

// 源代码 #include <stdio.h> /* * 2016/9/29 yu liang. */ int test_one(void) { int i1; char *p(char *)&i; if(*p1) printf("Little_endian\n"); // Little_endian else printf("B…

一文弄清楚Vue中的computed与watch的区别

1.实现业务当我们点击按钮&#xff0c;就会切换h1标签的语句内容&#xff0c;再次点击按钮&#xff0c;h1标签的语句内容就会恢复&#xff0c;每次点击按钮&#xff0c;浏览器都会输出一个语句来表达监视到了h1的内容改变2.Vue中的computed计算属性2.1利用Vue中的computed计算属…

Windows server——部署DHCP服务

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 本章重点 一.DHCP概述 1.DHCP服务的好处 二.DHCP的工作原理 1.DHCP的分配方…

【云原生 | 50】Docker三剑客之Docker Compose第一节

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

pinia和vuex的区别

pinia和vuex的区别 什么是“状态管理模式”&#xff1f; const Counter {// 状态data () {return {count: 0}},// 视图template: <div>{{ count }}</div>,// 操作methods: {increment () { this.count}} }createApp(Counter).mount(#app)这个状态自管理应用包含…

字符串题记

经典字符串leetcode题 文章目录经典字符串leetcode题反转字符串第一种方法&#xff1a;使用string里的库函数reverse第二种方法&#xff1a;使用自己写的swap函数第一种swap函数第二种swap函数151.翻转字符串里的单词28. 实现 strStr()KMP算法459.重复的子字符串第一种&#xf…

UE4 后期材质节点学习

以下对应的效果&#xff1a; 材质后期在这里进行设置&#xff1a; 在这里调整场景的整体的饱和度 场景的对比度 灰度系数的调整 高光度/图像增益 灰阶偏移的设置 想了解这些专业名词可以看&#xff1a;相机gain lift gamma offset参数意义_baobei0112的博客-CSDN博客_相机gai…

Redis学习笔记(一)Linux下安装部署Redis

一、下载Redis 1、进入官网&#xff0c;进入download页面 https://redis.io/download&#xff0c;找到“List of all releases and hash digests”&#xff0c;点击“ listing of all previous Redis releases on the releases page”&#xff0c;可以进入所有版本下载页面。 …

STM32——DMA直接存储器访问

文章目录一、DMA直接存储器存取DMA简介二、存储器映像三、DMA框图四、DMA基本结构五、DMA请求&#xff08;触发源&#xff09;六、数据宽度与对齐七、存储器到存储器的DMA转运原理图关键代码八、外设到存储器的DMA转运原理图硬件链接图关键代码九、其他一、DMA直接存储器存取 …

【图像分类】4.ResNet残差模块卷积网络的神

ResNet重要性不必多说了吧&#xff0c;论文引用破10w&#xff0c;是我见过最多的&#xff0c;yyds&#xff01; 在对照博主霹雳吧啦和官方pytorch的代码下&#xff0c;手撸一个resnet。如果没有看着代码写&#xff0c;不确定自己是否能根据论文写出model&#xff0c;而且写优雅…