大数据(8l)运费分摊

Posted 小基基o_O

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大数据(8l)运费分摊相关的知识,希望对你有一定的参考价值。

文章目录

问题描述

  • 电商场景中,优惠、运费等是以订单为单位进行计算的
  • 若要以商品维度进行分析,就要把优惠、运费等的效果分摊到每个商品
  • 分摊方法:
    分 摊 比 重 = 每 种 商 品 的 金 额 商 品 总 额 分摊比重=\\frac每种商品的金额商品总额 =
  • 问题来了,由于除法有时除不尽,导致合计有差
  • 改进方法:
    最 后 一 种 商 品 分 摊 比 重 = 1 − 其 它 分 摊 比 重 累 加 最后一种商品分摊比重 = 1 - 其它分摊比重累加 =1
  • 判断是否最后一种商品:
    商 品 总 额 − 已 经 分 摊 的 商 品 金 额 累 加 = = 商 品 金 额 商品总额 - 已经分摊的商品金额累加 == 商品金额 ==

Python实现

运费分摊

data = [
    ('a1', ['牛奶', '坚果', '蛋糕'], [30, 30, 30], 10, 100),
    ('a2', ['酸奶', '坚果', '蛋糕'], [60, 60, 60], 20, 200),
]

for 订单号, 订单商品, 订单商品金额, 运费, 订单总额 in data:
    商品总额 = 订单总额 - 运费
    已经分摊的商品金额累加 = 0
    运费分摊累加 = 0
    # 遍历每个商品,计算【运费分摊】
    for 商品, 商品金额 in zip(订单商品, 订单商品金额):
        # 判断是否为最后一个商品
        if 商品总额 - 已经分摊的商品金额累加 == 商品金额:
            运费分摊 = 运费 - 运费分摊累加
        else:
            运费分摊 = round(商品金额 / 商品总额 * 运费, 2)
            已经分摊的商品金额累加 += 商品金额
            运费分摊累加 += 运费分摊
        print(订单号, '\\033[033m', 商品, 商品金额, 运费分摊, '\\033[0m', 运费, 订单总额)

运费和优惠分摊

data = [
    ('a1', ['牛奶', '坚果', '蛋糕'], [30, 30, 30], 10, 20, 80),
    ('a2', ['酸奶', '坚果', '蛋糕'], [60, 60, 60], 20, 40, 160),
]

for 订单号, 订单商品, 订单商品金额, 运费, 优惠, 订单总额 in data:
    商品总额 = 订单总额 - 运费 + 优惠
    已经分摊的商品金额累加 = 0
    运费分摊累加 = 0
    优惠分摊累加 = 0
    # 遍历每个商品,计算【运费分摊】
    for 商品, 商品金额 in zip(订单商品, 订单商品金额):
        # 判断是否为最后一个商品
        if 商品总额 - 已经分摊的商品金额累加 == 商品金额:
            运费分摊 = 运费 - 运费分摊累加
            优惠分摊 = 优惠 - 优惠分摊累加
        else:
            已经分摊的商品金额累加 += 商品金额
            运费分摊 = round(商品金额 / 商品总额 * 运费, 2)
            运费分摊累加 += 运费分摊
            优惠分摊 = round(商品金额 / 商品总额 * 优惠, 2)
            优惠分摊累加 += 优惠分摊
        print(订单号, '\\033[033m', 商品, 商品金额, 运费分摊, 优惠分摊, '\\033[0m', 运费, 优惠, 订单总额)

打印

HIVE实现

--删库
DROP DATABASE IF EXISTS sale CASCADE;
--建库
CREATE DATABASE sale LOCATION '/sale';
USE sale;
--建表
CREATE TABLE good(
order_number    STRING COMMENT "订单号",
good            STRING COMMENT "商品",
good_costs      INT    COMMENT "商品金额",
goods_costs     INT    COMMENT "商品总额",
transport_costs INT    COMMENT "运费",
costs           INT    COMMENT "订单总额"
)COMMENT "商品分析"
LOCATION '/sale/good';
--插数据
INSERT INTO TABLE good VALUES
('a1','牛奶',3000,9000,1000,10000),
('a1','坚果',3000,9000,1000,10000),
('a1','蛋糕',3000,9000,1000,10000),
('a2','酸奶',6000,18000,2000,20000),
('a2','坚果',6000,18000,2000,20000),
('a2','蛋糕',6000,18000,2000,20000);
--查看
SELECT * FROM good;

good1

CREATE VIEW good1 AS
SELECT
    *,
    SUM(good_costs) OVER(PARTITION BY order_number ORDER BY good)
        AS good_accumulation,  -- 累计商品金额
    ROUND(good_costs/goods_costs*transport_costs)
        AS transport_share     -- 分摊运费
FROM good;

good2

CREATE VIEW good2 AS
SELECT
    *,
    SUM(transport_share) OVER(PARTITION BY order_number ORDER BY good)
        AS transport_share_accumulation  -- 累计分摊运费
FROM good1;

good3

CREATE VIEW good3 AS
SELECT
    *,
    IF(goods_costs==good_accumulation,transport_costs-transport_share_accumulation+transport_share,transport_share)
        AS transport_share_final         -- 最终分摊运费
FROM good2;

123合体

SELECT
    *,
    IF(
        goods_costs==good_accumulation,
        transport_costs-transport_share_accumulation+transport_share,
        transport_share)
        AS transport_share_final         -- 最终分摊运费
FROM (
    SELECT
        *,
        SUM(good_costs) OVER(PARTITION BY order_number ORDER BY good)
            AS good_accumulation,  -- 累计商品金额
        ROUND(good_costs/goods_costs*transport_costs)
            AS transport_share,    -- 分摊运费
        SUM(ROUND(good_costs/goods_costs*transport_costs))
            OVER(PARTITION BY order_number ORDER BY good)
            AS transport_share_accumulation  -- 累计分摊运费
    FROM good
)t;

Spark实现

import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession

object Hello 
  def main(args: Array[String]): Unit = 
    // 创建SparkSession对象
    val c1: SparkConf = new SparkConf().setAppName("a1").setMaster("local[*]")
    val spark: SparkSession = SparkSession.builder().config(c1).getOrCreate()
    // 隐式转换支持
    import spark.implicits._
    // 创建数据
    val df = Seq(
      ("a1", "牛奶", 3000, 9000, 1000, 10000),
      ("a1", "坚果", 3000, 9000, 1000, 10000),
      ("a1", "蛋糕", 3000, 9000, 1000, 10000),
      ("a2", "酸奶", 6000, 18000, 2000, 20000),
      ("a2", "坚果", 6000, 18000, 2000, 20000),
      ("a2", "蛋糕", 6000, 18000, 2000, 20000)
    ).toDF("order_number", "good", "good_costs", "goods_costs", "transport_costs", "costs"
    ).sort("order_number")
    // 创建视图
    df.createTempView("good")
    // 累计商品金额、分摊运费、累计分摊运费
    spark.sql(
      """
        |SELECT
        |    *,
        |    SUM(good_costs) OVER(PARTITION BY order_number ORDER BY good)
        |        AS good_accumulation,  -- 累计商品金额
        |    ROUND(good_costs/goods_costs*transport_costs)
        |        AS transport_share,    -- 分摊运费
        |    SUM(ROUND(good_costs/goods_costs*transport_costs))
        |        OVER(PARTITION BY order_number ORDER BY good)
        |        AS transport_share_accumulation  -- 累计分摊运费
        |FROM good
        |""".stripMargin).createTempView("good1")
    // 最终分摊运费
    spark.sql(
      """
        |SELECT
        |    *,
        |    IF(
        |        goods_costs==good_accumulation,
        |        transport_costs-transport_share_accumulation+transport_share,
        |        transport_share)
        |        AS transport_share_final         -- 最终分摊运费
        |FROM good1;
        |""".stripMargin).show()
  

结果打印

以上是关于大数据(8l)运费分摊的主要内容,如果未能解决你的问题,请参考以下文章

电商平台之运费分摊算法

大数据(3g)HIVE开窗函数应用场景(不定更)

按比例分摊金额怎么分

【请教】采购运费发票校验差异进了GR/IR科目,没进差异科目。啥原因,怎么解决?

记一次stm8l程序跑飞

请教各位,STM8L与STM8S在编程方面差别有多大