在spark中,对数据的查询和数据库是有点对其的,有条件查询也有全量查询
具体如何创建原始数据,请看上一篇博客(dataframe的8种创建方法)
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('increase delete change select').master('local').getOrCreate()
df = spark.createDataFrame([
['alex',1,2,'string1'],
['paul',11 ,12,'string2'],
['alex',21,22,'leon'],
['james',31,32,'traveler']],schema=('name string,a long, b long, c string'))
df.show()
+-----+---+---+--------+
| name| a| b| c|
+-----+---+---+--------+
| alex| 1| 2| string1|
| paul| 11| 12| string2|
| alex| 21| 22| leon|
|james| 31| 32|traveler|
+-----+---+---+--------+
对数据的条件查询其实是针对具体的列进行操作的,所以可以认为每一次的条件查询,都是要把条件施加到具体的某一列上,比如df.filter(df.age > 10),这个大于10的条件诗选就是实在具体的age列上的。
条件查询用filter,具体的格式如下:
df[‘筛选条件’]
df.filter(‘筛选条件’)
df.where(‘筛选条件’)
二者的用法一样,所以二选一讲解即可
1.1.在区间查询上,通常最常规的当让是可以利用关系运算符进行查询(> , < , == )
下图是筛选所有记录中,a列中大于20的数据记录
#这是利用关系运算符进行查询的,< 和 ==的查询类似
df.filter(df.a > 20).show()
+-----+---+---+--------+
| name| a| b| c|
+-----+---+---+--------+
| alex| 21| 22| leon|
|james| 31| 32|traveler|
+-----+---+---+--------+
df[df.a > 20].show()
+-----+---+---+--------+
| name| a| b| c|
+-----+---+---+--------+
| alex| 21| 22| leon|
|james| 31| 32|traveler|
+-----+---+---+--------+
1.2,between(lowerBound, upperBound)
查询最低值lowerBound到最高值upperBound之间的数据记录
下图是筛选所有记录中,a列中数据在10-30之间的数据记录
df.filter(df.a.between(10,30)).show()
+----+---+---+-------+
|name| a| b| c|
+----+---+---+-------+
|paul| 11| 12|string2|
|alex| 21| 22| leon|
+----+---+---+-------+
2.1 contains(other)
查询包含子串other的数据记录,通常这个other是一个字符串
下图是筛选所有记录中,c列值包含str的数据记录
值得注意的是:这个作为一个字串,在实际的查询的字符串中,它可以是任何位置,比如有一个之是string1,这里的other如果是in,那他会在string1中每一个位置搜寻in,找到就可
df.filter(df.c.contains('str')).show()
+----+---+---+-------+
|name| a| b| c|
+----+---+---+-------+
|alex| 1| 2|string1|
|paul| 11| 12|string2|
+----+---+---+-------+
2.2 like(str)
查询满足str条件的数据,通常这个str是一个由字符串和通配符组成的
下图是筛选所有记录中,c列值以on结尾的数据记录
值得注意是:这个on的位置是固定,必须是在尾部,因为前面有一个on的通配符,如果是on%,那on必须在开头,所以这个on的位置是由我们自己设定的,这点是和contains不同之处
df.filter(df.c.like('%on')).show()
+----+---+---+----+
|name| a| b| c|
+----+---+---+----+
|alex| 21| 22|leon|
+----+---+---+----+
2.3 startswith(other)
查询数据是以other开头的数据记录
下图是筛选所有记录中,c列值以str开头的数据记录
注意:这里其实好比是contains和like的特殊形式
df.filter(df.c.startswith('str')).show()
+----+---+---+-------+
|name| a| b| c|
+----+---+---+-------+
|alex| 1| 2|string1|
|paul| 11| 12|string2|
+----+---+---+-------+
2.4 endswith(other)
查询数据是以other结尾的数据记录
下图是筛选所有记录中,c列值以ing2结尾的数据记录
注意:这里其实好比是contains和like的特殊形式
df.filter(df.c.endswith('ing2')).show()
+----+---+---+-------+
|name| a| b| c|
+----+---+---+-------+
|paul| 11| 12|string2|
+----+---+---+-------+
2.5.isin(*cols)
查询具体列中,包含在cols下的数据,通常这可以叫具体查询
下图是筛选所有记录中,c列值为string1和Leon的数据记录
df.filter(df.c.isin(['string1','leon'])).show()
+----+---+---+-------+
|name| a| b| c|
+----+---+---+-------+
|alex| 1| 2|string1|
|alex| 21| 22| leon|
+----+---+---+-------+
3.1.isNotNull()
列中非空值筛选
下图是筛选所有记录中,a不为0的数据记录。
df.filter(df.a.isNotNull()).show()
+-----+---+---+--------+
| name| a| b| c|
+-----+---+---+--------+
| alex| 1| 2| string1|
| paul| 11| 12| string2|
| alex| 21| 22| leon|
|james| 31| 32|traveler|
+-----+---+---+--------+
3.2.isNull()
列中空值筛选
下图是筛选所有记录中,a为0的数据记录。
df.filter(df.a.isNull()).show()
+----+---+---+---+
|name| a| b| c|
+----+---+---+---+
+----+---+---+---+
具体格式如下:
df.select(要显示的列)
df[要显示的列]
1.1第一种查询,用’.'来表示列
下图是查询a列和c列
df.select(df.a,df.c).show()
+---+--------+
| a| c|
+---+--------+
| 1| string1|
| 11| string2|
| 21| leon|
| 31|traveler|
+---+--------+
1.2.第二种查询,用[]来表示列
下图是查询a列和c列
df.select(df['a'],df['c']).show()
+---+--------+
| a| c|
+---+--------+
| 1| string1|
| 11| string2|
| 21| leon|
| 31|traveler|
+---+--------+
同样的,对于这样的方式,你可以有三种写法:
第一种就是利用’.‘来访问列,比如:df[ df.a,df.c ]
第二种就是利用[]来访问列,比如:df[ df[‘a’] , df[‘c’] ]
第三种就是利用’.'来访问列,比如:df[ ‘a’,‘c’ ]
下图是查询a列和c列
df[[df.a,df.c]]
DataFrame[a: bigint, c: string]
#3.全量查询的第三种表达
df['a','c'].show()
+---+--------+
| a| c|
+---+--------+
| 1| string1|
| 11| string2|
| 21| leon|
| 31|traveler|
+---+--------+
全量查询也可以加筛选条件,但是和条件查询的差异在于,它不会将不符合条件的值筛选掉,而是会将施加筛选条件的那一列二值化,不符合条件的为false,符合条件的为true
df.select(df.a,df.b> 20 ).show()
+---+--------+
| a|(b > 20)|
+---+--------+
| 1| false|
| 11| false|
| 21| true|
| 31| true|
+---+--------+
接着上面的说,上面的例子可以将符合条件的变为true,不符合的变为false,那具体的应用场景是什么呢?
我们还能做些什么呢?,我们可以进行批量改写,这时候就引出一个when…otherwise()
这个when的api是在functions下,若以需要进行额外的引入
下图是将b列中,大于20的改为888,否则就为999
from pyspark.sql import functions as F
df.select(df.a,F.when(df.b > 20, 888).otherwise(999)).show()
+---+----------------------------------------+
| a|CASE WHEN (b > 20) THEN 888 ELSE 999 END|
+---+----------------------------------------+
| 1| 999|
| 11| 999|
| 21| 888|
| 31| 888|
+---+----------------------------------------+
下图是将b列中,大于20的改为888,小于10的改为666,否则就为999
df.select(df.a,F.when(df.b > 20, 888).when(df.b < 10,666).otherwise(999)).show()
+---+---------------------------------------------------------------+
| a|CASE WHEN (b > 20) THEN 888 WHEN (b < 10) THEN 666 ELSE 999 END|
+---+---------------------------------------------------------------+
| 1| 666|
| 11| 999|
| 21| 888|
| 31| 888|
+---+---------------------------------------------------------------+
从以上的几个例子发现施加条件筛选后的列名奇奇怪怪,很长,这显然不是我们想要的,zip时候可以对其进行列名的修改,将其改为原来的列名
.alias(‘列名’)
.name(‘列名’)
下面举个例子:
未改列名之前,列名很长
df.select(df.a,F.when(df.b > 20, 888).when(df.b < 10,666).otherwise(999)).show()
+---+---------------------------------------------------------------+
| a|CASE WHEN (b > 20) THEN 888 WHEN (b < 10) THEN 666 ELSE 999 END|
+---+---------------------------------------------------------------+
| 1| 666|
| 11| 999|
| 21| 888|
| 31| 888|
+---+---------------------------------------------------------------+
修改列名后
df.select(df.a,F.when(df.b > 20, 888).when(df.b < 10,666).otherwise(999).alias('b')).show()
+---+---+
| a| b|
+---+---+
| 1|666|
| 11|999|
| 21|888|
| 31|888|
+---+---+
df.select(df.a,F.when(df.b > 20, 888).when(df.b < 10,666).otherwise(999).name('b')).show()
+---+---+
| a| b|
+---+---+
| 1|666|
| 11|999|
| 21|888|
| 31|888|
+---+---+
有时候想对数据进行类型转换,比如将某一列的bingint型转为string类型这样,可以有两种方法。
一种方法是astype();
一种方法是case();
二者的用法是完全一致的
df
DataFrame[name: string, a: bigint, b: bigint, c: string]
df[df.a,df.b.astype('string'),df.c]
DataFrame[a: bigint, b: string, c: string]
df[df.a.cast('string'),df.b.astype('string'),df.c]
DataFrame[a: string, b: string, c: string]