SparkSQL综合案例-省份维度的销售情况统计分析

一、项目背景

二、项目需求

        (1)需求

        ①各省销售指标,每个省份的销售额统计

        ②TOP3销售省份中,有多少家店铺日均销售额1000+

        ③TOP3省份中,各个省份的平均单价

        ④TOP3省份中,各个省份的支付类型比例

        (2)要求

        ①将需求结果写出到mysql

        ②将数据写入到Spark On Hive中

三、代码实现

        (1)需求1:
# cording:utf8
'''
要求1:各省销售额统计
要求2:TOP3销售省份中,有多少店铺达到过日销售额1000+
要求3:TOP3省份中,各省的平均单单价
要求4:TOP3省份中,各个省份的支付类型比例
'''

from pyspark.sql import SparkSession
from pyspark.sql import functions as F
if __name__ == '__main__':
    spark = SparkSession.builder.appName('SQL_text').\
        master('local[*]').\
        config('spark.sql.shuffle.partitions', '2').\
        config('spark.sql.warehouse.dir', 'hdfs://pyspark01/user/hive/warehouse').\
        config('hive.metastore.uris', 'thrift://pyspark01:9083').\
        enableHiveSupport().\
        getOrCreate()
    # 1.读取数据
    # 省份信息,缺失值过滤,同时省份信息中会有‘null’字符串
    # 订单的金额,数据集中有订单的金额是单笔超过10000的,这些事测试数据
    # 列值过滤(SparkSQL会自动做这个优化)
    df = spark.read.format('json').load('../../input/mini.json').\
        dropna(thresh=1, subset=['storeProvince']).\
        filter("storeProvince != 'null'").\
        filter('receivable < 10000').\
        select('storeProvince', 'storeID', 'receivable', 'dateTS', 'payType')

    # TODO 1:各省销售额统计
    province_sale_df = df.groupBy('storeProvince').sum('receivable').\
        withColumnRenamed('sum(receivable)', 'money').\
        withColumn('money', F.round('money', 2)).\
        orderBy('money', ascending=False)
    province_sale_df.show(truncate=False)

    # 写出到Mysql
    province_sale_df.write.mode('overwrite').\
        format('jdbc').\
        option('url', 'jdbc:mysql://pyspark01:3306/bigdata?useSSL=False&useUnicode=true&characterEncoding=utf8').\
        option('dbtable', 'province_sale').\
        option('user', 'root').\
        option('password', 'root').\
        option('encoding', 'utf8').\
        save()

    # 写出Hive表 saveAsTable 可以写出表 要求已经配置好spark on hive
    # 会将表写入到hive的数据仓库中
    province_sale_df.write.mode('overwrite').saveAsTable('default.province_sale', 'parquet')

        结果展示:

        MySQL数据展示:

        Hive数据展示:

        (2)需求2:
# cording:utf8
'''
要求1:各省销售额统计
要求2:TOP3销售省份中,有多少店铺达到过日销售额1000+
要求3:TOP3省份中,各省的平均单单价
要求4:TOP3省份中,各个省份的支付类型比例
'''

from pyspark.sql import SparkSession
from pyspark.sql import functions as F
from pyspark.storagelevel import StorageLevel

if __name__ == '__main__':
    spark = SparkSession.builder.appName('SQL_text').\
        master('local[*]').\
        config('spark.sql.shuffle.partitions', '2').\
        config('spark.sql.warehouse.dir', 'hdfs://pyspark01/user/hive/warehouse').\
        config('hive.metastore.uris', 'thrift://pyspark01:9083').\
        enableHiveSupport().\
        getOrCreate()
    # 1.读取数据
    # 省份信息,缺失值过滤,同时省份信息中会有‘null’字符串
    # 订单的金额,数据集中有订单的金额是单笔超过10000的,这些事测试数据
    # 列值过滤(SparkSQL会自动做这个优化)
    df = spark.read.format('json').load('../../input/mini.json').\
        dropna(thresh=1, subset=['storeProvince']).\
        filter("storeProvince != 'null'").\
        filter('receivable < 10000').\
        select('storeProvince', 'storeID', 'receivable', 'dateTS', 'payType')

    # TODO 1:各省销售额统计
    province_sale_df = df.groupBy('storeProvince').sum('receivable').\
        withColumnRenamed('sum(receivable)', 'money').\
        withColumn('money', F.round('money', 2)).\
        orderBy('money', ascending=False)
    # # 写出到Mysql
    # province_sale_df.write.mode('overwrite').\
    #     format('jdbc').\
    #     option('url', 'jdbc:mysql://pyspark01:3306/bigdata?useSSL=False&useUnicode=true&characterEncoding=utf8').\
    #     option('dbtable', 'province_sale').\
    #     option('user', 'root').\
    #     option('password', 'root').\
    #     option('encoding', 'utf8').\
    #     save()
    #
    # # 写出Hive表 saveAsTable 可以写出表 要求已经配置好spark on hive
    # # 会将表写入到hive的数据仓库中
    # province_sale_df.write.mode('overwrite').saveAsTable('default.province_sale', 'parquet')

    # TODO 需求2:TOP3销售省份中,有多少店铺达到过日销售额1000+
    # 2.1 找到TOP3的销售省份
    top3_province_df = province_sale_df.limit(3).select('storeProvince').\
        withColumnRenamed('storeProvince', 'top3_province')     # 对列名进行重命名,防止与province_sale_df的storeProvince冲突

    # 2.2 和原始的DF进行内关联,数据关联后,得到TOP3省份的销售数据
    top3_province_df_joined = df.join(top3_province_df, on=df['storeProvince'] == top3_province_df['top3_province'])

    # 因为需要多次使用到TOP3省份数据,所有对其进行持久化缓存
    top3_province_df_joined.persist(StorageLevel.MEMORY_AND_DISK)

    # from_unixtime将秒级的日期数据转换为年月日数据
    # from_unixtime的精度是秒级,数据的精度是毫秒级,需要对数据进行进度的裁剪
    province_hot_store_count_df = top3_province_df_joined.groupBy("storeProvince", "storeID",
                        F.from_unixtime(df['dateTS'].substr(0, 10), "yyyy-mm-dd").alias('day')).\
                        sum('receivable').withColumnRenamed('sum(receivable)', 'money').\
                         filter('money > 1000 ').\
                        dropDuplicates(subset=['storeID']).\
                        groupBy('storeProvince').count()
    province_hot_store_count_df.show()
    # 写出到Mysql
    province_sale_df.write.mode('overwrite'). \
        format('jdbc'). \
        option('url', 'jdbc:mysql://pyspark01:3306/bigdata?useSSL=False&useUnicode=true&characterEncoding=utf8'). \
        option('dbtable', 'province_hot_store_count'). \
        option('user', 'root'). \
        option('password', 'root'). \
        option('encoding', 'utf8'). \
        save()

    # 写出Hive表 saveAsTable 可以写出表 要求已经配置好spark on hive
    # 会将表写入到hive的数据仓库中
    province_sale_df.write.mode('overwrite').saveAsTable('default.province_hot_store_count', 'parquet')

    top3_province_df_joined.unpersist()

        结果展示:

        MySQL结果展示:

        Hive结果展示:

        (3)需求3:
# cording:utf8
'''
要求1:各省销售额统计
要求2:TOP3销售省份中,有多少店铺达到过日销售额1000+
要求3:TOP3省份中,各省的平均单单价
要求4:TOP3省份中,各个省份的支付类型比例
'''

from pyspark.sql import SparkSession
from pyspark.sql import functions as F
from pyspark.storagelevel import StorageLevel

if __name__ == '__main__':
    spark = SparkSession.builder.appName('SQL_text').\
        master('local[*]').\
        config('spark.sql.shuffle.partitions', '2').\
        config('spark.sql.warehouse.dir', 'hdfs://pyspark01/user/hive/warehouse').\
        config('hive.metastore.uris', 'thrift://pyspark01:9083').\
        enableHiveSupport().\
        getOrCreate()
    # 1.读取数据
    # 省份信息,缺失值过滤,同时省份信息中会有‘null’字符串
    # 订单的金额,数据集中有订单的金额是单笔超过10000的,这些事测试数据
    # 列值过滤(SparkSQL会自动做这个优化)
    df = spark.read.format('json').load('../../input/mini.json').\
        dropna(thresh=1, subset=['storeProvince']).\
        filter("storeProvince != 'null'").\
        filter('receivable < 10000').\
        select('storeProvince', 'storeID', 'receivable', 'dateTS', 'payType')

    # TODO 1:各省销售额统计
    province_sale_df = df.groupBy('storeProvince').sum('receivable').\
        withColumnRenamed('sum(receivable)', 'money').\
        withColumn('money', F.round('money', 2)).\
        orderBy('money', ascending=False)
    # # 写出到Mysql
    # province_sale_df.write.mode('overwrite').\
    #     format('jdbc').\
    #     option('url', 'jdbc:mysql://pyspark01:3306/bigdata?useSSL=False&useUnicode=true&characterEncoding=utf8').\
    #     option('dbtable', 'province_sale').\
    #     option('user', 'root').\
    #     option('password', 'root').\
    #     option('encoding', 'utf8').\
    #     save()
    #
    # # 写出Hive表 saveAsTable 可以写出表 要求已经配置好spark on hive
    # # 会将表写入到hive的数据仓库中
    # province_sale_df.write.mode('overwrite').saveAsTable('default.province_sale', 'parquet')

    # TODO 需求2:TOP3销售省份中,有多少店铺达到过日销售额1000+
    # 2.1 找到TOP3的销售省份
    top3_province_df = province_sale_df.limit(3).select('storeProvince').\
        withColumnRenamed('storeProvince', 'top3_province')     # 对列名进行重命名,防止与province_sale_df的storeProvince冲突

    # 2.2 和原始的DF进行内关联,数据关联后,得到TOP3省份的销售数据
    top3_province_df_joined = df.join(top3_province_df, on=df['storeProvince'] == top3_province_df['top3_province'])

    # 因为需要多次使用到TOP3省份数据,所有对其进行持久化缓存
    top3_province_df_joined.persist(StorageLevel.MEMORY_AND_DISK)

    # from_unixtime将秒级的日期数据转换为年月日数据
    # from_unixtime的精度是秒级,数据的精度是毫秒级,需要对数据进行进度的裁剪
    province_hot_store_count_df = top3_province_df_joined.groupBy("storeProvince", "storeID",
                        F.from_unixtime(df['dateTS'].substr(0, 10), "yyyy-mm-dd").alias('day')).\
                        sum('receivable').withColumnRenamed('sum(receivable)', 'money').\
                         filter('money > 1000 ').\
                        dropDuplicates(subset=['storeID']).\
                        groupBy('storeProvince').count()
    province_hot_store_count_df.show()
    # # 写出到Mysql
    # province_hot_store_count_df.write.mode('overwrite'). \
    #     format('jdbc'). \
    #     option('url', 'jdbc:mysql://pyspark01:3306/bigdata?useSSL=False&useUnicode=true&characterEncoding=utf8'). \
    #     option('dbtable', 'province_hot_store_count'). \
    #     option('user', 'root'). \
    #     option('password', 'root'). \
    #     option('encoding', 'utf8'). \
    #     save()
    #
    # # 写出Hive表 saveAsTable 可以写出表 要求已经配置好spark on hive
    # # 会将表写入到hive的数据仓库中
    # province_hot_store_count_df.write.mode('overwrite').saveAsTable('default.province_hot_store_count', 'parquet')


    # TODO 3:TOP3省份中,各省的平均单单价
    top3_province_order_avg_df = top3_province_df_joined.groupBy("storeProvince").\
        avg("receivable").\
        withColumnRenamed("avg(receivable)", "money").\
        withColumn("money", F.round("money", 2)).\
        orderBy("money", ascending=False)
    top3_province_order_avg_df.show(truncate=False)

    # 写出到Mysql
    top3_province_order_avg_df.write.mode('overwrite'). \
        format('jdbc'). \
        option('url', 'jdbc:mysql://pyspark01:3306/bigdata?useSSL=False&useUnicode=true&characterEncoding=utf8'). \
        option('dbtable', 'top3_province_order_avg'). \
        option('user', 'root'). \
        option('password', 'root'). \
        option('encoding', 'utf8'). \
        save()

    # 写出Hive表 saveAsTable 可以写出表 要求已经配置好spark on hive
    # 会将表写入到hive的数据仓库中
    top3_province_order_avg_df.write.mode('overwrite').saveAsTable('default.top3_province_order_avg', 'parquet')

    top3_province_df_joined.unpersist()

        结果展示

        MySQL与Hive结果展示:

        (4)需求4:
# cording:utf8
'''
要求1:各省销售额统计
要求2:TOP3销售省份中,有多少店铺达到过日销售额1000+
要求3:TOP3省份中,各省的平均单单价
要求4:TOP3省份中,各个省份的支付类型比例
'''

from pyspark.sql import SparkSession
from pyspark.sql import functions as F
from pyspark.storagelevel import StorageLevel
from pyspark.sql.types import StringType
if __name__ == '__main__':
    spark = SparkSession.builder.appName('SQL_text').\
        master('local[*]').\
        config('spark.sql.shuffle.partitions', '2').\
        config('spark.sql.warehouse.dir', 'hdfs://pyspark01/user/hive/warehouse').\
        config('hive.metastore.uris', 'thrift://pyspark01:9083').\
        enableHiveSupport().\
        getOrCreate()
    # 1.读取数据
    # 省份信息,缺失值过滤,同时省份信息中会有‘null’字符串
    # 订单的金额,数据集中有订单的金额是单笔超过10000的,这些事测试数据
    # 列值过滤(SparkSQL会自动做这个优化)
    df = spark.read.format('json').load('../../input/mini.json').\
        dropna(thresh=1, subset=['storeProvince']).\
        filter("storeProvince != 'null'").\
        filter('receivable < 10000').\
        select('storeProvince', 'storeID', 'receivable', 'dateTS', 'payType')

    # TODO 1:各省销售额统计
    province_sale_df = df.groupBy('storeProvince').sum('receivable').\
        withColumnRenamed('sum(receivable)', 'money').\
        withColumn('money', F.round('money', 2)).\
        orderBy('money', ascending=False)
    # # 写出到Mysql
    # province_sale_df.write.mode('overwrite').\
    #     format('jdbc').\
    #     option('url', 'jdbc:mysql://pyspark01:3306/bigdata?useSSL=False&useUnicode=true&characterEncoding=utf8').\
    #     option('dbtable', 'province_sale').\
    #     option('user', 'root').\
    #     option('password', 'root').\
    #     option('encoding', 'utf8').\
    #     save()
    #
    # # 写出Hive表 saveAsTable 可以写出表 要求已经配置好spark on hive
    # # 会将表写入到hive的数据仓库中
    # province_sale_df.write.mode('overwrite').saveAsTable('default.province_sale', 'parquet')

    # TODO 需求2:TOP3销售省份中,有多少店铺达到过日销售额1000+
    # 2.1 找到TOP3的销售省份
    top3_province_df = province_sale_df.limit(3).select('storeProvince').\
        withColumnRenamed('storeProvince', 'top3_province')     # 对列名进行重命名,防止与province_sale_df的storeProvince冲突

    # 2.2 和原始的DF进行内关联,数据关联后,得到TOP3省份的销售数据
    top3_province_df_joined = df.join(top3_province_df, on=df['storeProvince'] == top3_province_df['top3_province'])

    # 因为需要多次使用到TOP3省份数据,所有对其进行持久化缓存
    top3_province_df_joined.persist(StorageLevel.MEMORY_AND_DISK)

    # from_unixtime将秒级的日期数据转换为年月日数据
    # from_unixtime的精度是秒级,数据的精度是毫秒级,需要对数据进行进度的裁剪
    province_hot_store_count_df = top3_province_df_joined.groupBy("storeProvince", "storeID",
                        F.from_unixtime(df['dateTS'].substr(0, 10), "yyyy-mm-dd").alias('day')).\
                        sum('receivable').withColumnRenamed('sum(receivable)', 'money').\
                         filter('money > 1000 ').\
                        dropDuplicates(subset=['storeID']).\
                        groupBy('storeProvince').count()
    province_hot_store_count_df.show()
    # # 写出到Mysql
    # province_hot_store_count_df.write.mode('overwrite'). \
    #     format('jdbc'). \
    #     option('url', 'jdbc:mysql://pyspark01:3306/bigdata?useSSL=False&useUnicode=true&characterEncoding=utf8'). \
    #     option('dbtable', 'province_hot_store_count'). \
    #     option('user', 'root'). \
    #     option('password', 'root'). \
    #     option('encoding', 'utf8'). \
    #     save()
    #
    # # 写出Hive表 saveAsTable 可以写出表 要求已经配置好spark on hive
    # # 会将表写入到hive的数据仓库中
    # province_hot_store_count_df.write.mode('overwrite').saveAsTable('default.province_hot_store_count', 'parquet')


    # TODO 3:TOP3省份中,各省的平均单单价
    top3_province_order_avg_df = top3_province_df_joined.groupBy("storeProvince").\
        avg("receivable").\
        withColumnRenamed("avg(receivable)", "money").\
        withColumn("money", F.round("money", 2)).\
        orderBy("money", ascending=False)
    top3_province_order_avg_df.show(truncate=False)

    # # 写出到Mysql
    # top3_province_order_avg_df.write.mode('overwrite'). \
    #     format('jdbc'). \
    #     option('url', 'jdbc:mysql://pyspark01:3306/bigdata?useSSL=False&useUnicode=true&characterEncoding=utf8'). \
    #     option('dbtable', 'top3_province_order_avg'). \
    #     option('user', 'root'). \
    #     option('password', 'root'). \
    #     option('encoding', 'utf8'). \
    #     save()
    #
    # # 写出Hive表 saveAsTable 可以写出表 要求已经配置好spark on hive
    # # 会将表写入到hive的数据仓库中
    # top3_province_order_avg_df.write.mode('overwrite').saveAsTable('default.top3_province_order_avg', 'parquet')

    # TODO 4:TOP3省份中,各个省份的支付类型比例
    top3_province_df_joined.createTempView("province_pay")

    # 自定义UDF
    def udf_func(percent):
        return str(round(percent * 100)) + "%"
    # 注册UDF
    my_udf = F.udf(udf_func, StringType())

    pay_type_df = spark.sql('''
        SELECT storeProvince, payType, (count(payType) / total) AS percent FROM 
        (SELECT storeProvince, payType, count(1) OVER(PARTITION BY storeProvince) AS total FROM province_pay) AS sub
        GROUP BY storeProvince, payType, total
    ''').withColumn('percent', my_udf("percent"))
    pay_type_df.show()

    # 写出到Mysql
    pay_type_df.write.mode('overwrite'). \
        format('jdbc'). \
        option('url', 'jdbc:mysql://pyspark01:3306/bigdata?useSSL=False&useUnicode=true&characterEncoding=utf8'). \
        option('dbtable', 'pay_type'). \
        option('user', 'root'). \
        option('password', 'root'). \
        option('encoding', 'utf8'). \
        save()

    # 写出Hive表 saveAsTable 可以写出表 要求已经配置好spark on hive
    # 会将表写入到hive的数据仓库中
    top3_province_order_avg_df.write.mode('overwrite').saveAsTable('default.pay_type', 'parquet')

    top3_province_df_joined.unpersist()

       结果展示:

       MySQL结果展示:

        Hive结果展示:

四、项目运行问题及解决方法

        报错:java.sql.BatchUpdateException: Incorrect string value: '\xE6\xB1\x9F\xE8\xA5\xBF...' for column 'storeProvince' atrow1

        原因:MySQL的UTF-8只支持3个字节的unicode字符,无法支持四个字节的Unicode字符

        解决办法:在MySQL控制台执行下列代码修改编码格式

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
【课程大纲】 01.Storm项目实战课程大纲 02.CDH5搭建之CM5安装部署 03.CDH5搭建和CM界面化集群管理 04.Hadoop、HBase、Zookeeper集群管理和角色分配 05.Kafka基础知识和集群搭建 06.Kafka基本操作和最优设置 07.Kafka Java API 简单开发测试 08.storm-kafka 详解和实战案例 09.S图表框架HighCharts介绍 10.HBase快速入门 11.基于HBase的Dao基类和实现类开发一 12.基于HBase的Dao基类和实现类开发二 13.项目1-地区销售额-需求分析和架构设计 14.项目1-地区销售额-Spout融合Kafka Consumer及线程安全测试 15.项目1-地区销售额-Bolt业务逻辑处理一 16.项目1-地区销售额-优化Bolt支持重启及结果数据核查 17.项目1-地区销售额-HighCharts图表开发一及Web端架构设计 18.项目1-地区销售额-HTTP长链接实现实时推送 19.项目1-地区销售额-HighCharts图表开发二及jquery运用 20.项目1-地区销售额-Web端完善和细节优化 21.项目1-地区销售额-项目发布及总结 22.项目1-地区销售额-项目需求分析和分区Trident Spout开发 23.项目1-地区销售额-Trident代码开发一 24.项目1-地区销售额-Trident代码开发二 25.项目1-地区销售额-基于HBase存储的State运用 26.项目2-省份销售排行-双纵轴HighCharts图表开发一 27.项目2-省份销售排行-双纵轴HighCharts图表开发二 28.项目2-省份销售排行-双纵轴HighCharts图表开发三 29.项目2-省份销售排行-前台和图表交互开发和Top N实现 30.项目2-省份销售排行-Top N展示优化和项目开发思路总结 31.项目2-效果展示及项目3需求分析梳理 32.项目3-非跳出UV-Storm topology开发一 33.项目3-非跳出UV-Storm topology开发二 34.项目3-非跳出UV-Web端Servlet开发 35.项目3-非跳出UV-Web端Highcharts图表开发 36.项目3-非跳出UV-项目效果调试 37.项目3-非跳出UV-项目整体运行 38.项目3-非跳出UV-升级图表增加柱图一 39.项目3-非跳出UV-升级图表增加柱图二 40.JStorm介绍 41.会员问题收集和解答

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吗喽也是命

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值