【Hive SQL 每日一题】统计各个商品今年销售额与去年销售额的增长率及排名变化

文章目录

测试数据

sql 复制代码
-- 创建商品表
DROP TABLE IF EXISTS products;
CREATE TABLE products (
    product_id INT,
    product_name STRING
);

INSERT INTO products VALUES
(1, 'Product A'),
(2, 'Product B'),
(3, 'Product C'),
(4, 'Product D'),
(5, 'Product E'),
(6, 'Product F'),
(7, 'Product G'),
(8, 'Product H'),
(9, 'Product I'),
(10, 'Product J'),
(11, 'Product K');

-- 创建销售表
DROP TABLE IF EXISTS sales;
CREATE TABLE sales (
    sale_id INT,
    product_id INT,
    sale_date STRING,
    amount DOUBLE
);

INSERT INTO sales VALUES
(101, 1, '2023-01-01', 100.0),
(102, 1, '2023-02-01', 150.0),
(103, 2, '2023-03-01', 200.0),
(104, 3, '2023-04-01', 50.0),
(105, 4, '2023-05-01', 300.0),
(106, 5, '2023-06-01', 250.0),
(107, 1, '2024-01-01', 120.0),
(108, 1, '2024-02-01', 180.0),
(109, 2, '2024-03-01', 220.0),
(110, 3, '2024-04-01', 70.0),
(111, 4, '2024-05-01', 330.0),
(112, 5, '2024-06-01', 270.0),
(113, 2, '2023-07-01', 180.0),
(114, 3, '2023-08-01', 60.0),
(115, 4, '2023-09-01', 310.0),
(116, 5, '2023-10-01', 260.0),
(117, 1, '2023-11-01', 190.0),
(118, 2, '2023-12-01', 210.0),
(119, 3, '2024-01-01', 75.0),
(120, 4, '2024-02-01', 340.0),
(121, 5, '2024-03-01', 280.0),
(122, 6, '2023-01-01', 130.0),
(123, 6, '2023-02-01', 160.0),
(124, 7, '2023-03-01', 190.0),
(125, 8, '2023-04-01', 220.0),
(126, 9, '2023-05-01', 250.0),
(127, 10, '2023-06-01', 280.0),
(128, 6, '2024-01-01', 140.0),
(129, 6, '2024-02-01', 170.0),
(130, 7, '2024-03-01', 200.0),
(131, 8, '2024-04-01', 230.0),
(132, 9, '2024-05-01', 260.0),
(133, 10, '2024-06-01', 290.0),
(134, 7, '2023-07-01', 175.0),
(135, 8, '2023-08-01', 205.0),
(136, 9, '2023-09-01', 235.0),
(137, 10, '2023-10-01', 265.0),
(138, 6, '2023-11-01', 145.0),
(139, 7, '2023-12-01', 175.0),
(140, 8, '2024-01-01', 215.0),
(141, 9, '2024-02-01', 245.0),
(142, 10, '2024-03-01', 275.0),
(143, 6, '2024-04-01', 155.0),
(144, 7, '2024-05-01', 185.0),
(145, 8, '2024-06-01', 225.0),
(147, 11, '2023-06-09', 0.0),
(146, 11, '2024-06-01', 233.0);

需求说明

统计各个商品今年销售额与去年销售额的增长率及销售额的排名变化。

增长率计算公式:(当期份额-上期份额)/ 上期份额 * 100%

结果示例:

product_name total_amount_2023 total_amount_2024 growth_rate rk_2023 rk_2024 rk_diff
Product D 610.0 670.0 9.8% 1 1 0
Product H 425.0 670.0 57.6% 9 1 8
Product J 545.0 565.0 3.7% 3 3 0
Product E 510.0 550.0 7.8% 5 4 1
Product I 485.0 505.0 4.1% 6 5 1
... ... ... ... ... ... ...

其中:

  • product_name 表示商品名称;
  • total_amount_2023 表示商品在 2023 年度的销售额;
  • total_amount_2024 表示商品在 2024 年度的销售额;
  • growth_rate 表示商品的增长率;
  • rk_2023 表示商品在 2023 年度中的销售额排名;
  • rk_2024 表示商品在 2024 年度中的销售额排名;
  • rk_diff 表示该商品年度销售额排名的变化。

注意,在这里商品销售额可能存在两种情况:

  1. 假设某商品 2023 年销售 0.0,而在 2024 年销售 50,那么这种情况下,销售额增长率统一设置为 100.0%
  2. 如果在两个年度销售均为 0.0,那么销售额增长率设置为 0.0%

需求实现

sql 复制代码
SELECT
    p.product_name,
    total_amount_2023,
    total_amount_2024,
    CASE WHEN total_amount_2024=0 AND total_amount_2023=0
        THEN "0.0%"
        WHEN total_amount_2023=0
        THEN "100.0%"
        ELSE
            CONCAT(CAST((total_amount_2024 - total_amount_2023) / total_amount_2023 as DECIMAL(5,3)) * 100,"%")
    END growth_rate,
    rk_2023,
    rk_2024,
    rk_2024 - rk_2023 rk_diff
FROM
    (SELECT
        product_id,
        total_amount_2023,
        total_amount_2024,
        RANK() OVER(ORDER BY total_amount_2023 DESC) rk_2023,
        RANK() OVER(ORDER BY total_amount_2024 DESC) rk_2024
    FROM
        (SELECT
            product_id,
            SUM(IF(year(sale_date)="2023",amount,0)) total_amount_2023,
            SUM(IF(year(sale_date)="2024",amount,0)) total_amount_2024
        FROM
            sales
        WHERE
            year(sale_date) IN ("2023","2024")
        GROUP BY
            product_id)t1 
        )t2
JOIN
    products p
ON
    t2.product_id = p.product_id;

输出结果如下:

分步解析

(1)获取去年与今年两个年度的数据,并进行聚合统计。

sql 复制代码
SELECT
    product_id,
    SUM(IF(year(sale_date)="2023",amount,0)) total_amount_2023,
    SUM(IF(year(sale_date)="2024",amount,0)) total_amount_2024
FROM
    sales
WHERE
    year(sale_date) IN ("2023","2024")
GROUP BY
    product_id;

(2)根据(1)中的结果,通过窗口函数排序,获取分别获取两个年度的销售额排名。

sql 复制代码
SELECT
    product_id,
    total_amount_2023,
    total_amount_2024,
    RANK() OVER(ORDER BY total_amount_2023 DESC) rk_2023,
    RANK() OVER(ORDER BY total_amount_2024 DESC) rk_2024
FROM
    (SELECT
        product_id,
        SUM(IF(year(sale_date)="2023",amount,0)) total_amount_2023,
        SUM(IF(year(sale_date)="2024",amount,0)) total_amount_2024
    FROM
        sales
    WHERE
        year(sale_date) IN ("2023","2024")
    GROUP BY
        product_id)t1;

(3)根据(2)中的结果,判断并计算两个年度的增长率以及排名变化,最终通过 join 连接商品表,获取商品名称。

sql 复制代码
SELECT
    p.product_name,
    total_amount_2023,
    total_amount_2024,
    CASE WHEN total_amount_2024=0 AND total_amount_2023=0
        THEN "0.0%"
        WHEN total_amount_2023=0
        THEN "100.0%"
        ELSE
            CONCAT(CAST((total_amount_2024 - total_amount_2023) / total_amount_2023 as DECIMAL(5,3)) * 100,"%")
    END growth_rate,
    rk_2023,
    rk_2024,
    rk_2023 - rk_2024 rk_diff
FROM
    (SELECT
        product_id,
        total_amount_2023,
        total_amount_2024,
        RANK() OVER(ORDER BY total_amount_2023 DESC) rk_2023,
        RANK() OVER(ORDER BY total_amount_2024 DESC) rk_2024
    FROM
        (SELECT
            product_id,
            SUM(IF(year(sale_date)="2023",amount,0)) total_amount_2023,
            SUM(IF(year(sale_date)="2024",amount,0)) total_amount_2024
        FROM
            sales
        WHERE
            year(sale_date) IN ("2023","2024")
        GROUP BY
            product_id)t1 
        )t2
JOIN
    products p
ON
    t2.product_id = p.product_id;

可能对于排名那里存在疑惑,为什么是 rk_2023 - rk_2024,不是 rk_2024 - rk_2023 呢?

惯性思维导致,在排序中,并不是排名越高值越大,相反,因为我们的排名越靠前(越高),其排名值越小,想到这里,就应该明白了。

相关推荐
Csvn4 小时前
📊 SQL 入门 Day 8:集合操作 — 用 SQL 做数学里的"并交差"
后端·sql
wang_yb6 小时前
当散点图不够用时:用 t-SNE 可视化多维数据
数据分析·databook
databook6 小时前
当散点图不够用时:用 t-SNE 可视化多维数据
python·数据分析·数据可视化
2501_933670796 小时前
电子信息工程零项目经验求职破局
数据分析
Irene199110 小时前
大数据开发的常见实践:把 SQL 直接写在 Shell 脚本里 ER图 数据血缘
sql·数据血缘·er
川石课堂软件测试10 小时前
安全测试|常见SQL注入攻击方式、实例及预防
服务器·数据库·sql·功能测试·测试工具·安全·单元测试
qq_3660862212 小时前
sql 查询中关于 null 值判断的问题
数据库·sql
AC赳赳老秦13 小时前
OpenClaw 采集任务日志审计:全程记录采集行为,满足合规溯源与企业审计要求
java·大数据·python·数据挖掘·数据分析·php·openclaw
迈巴赫车主13 小时前
湖仓一体(Data Lakehouse)简介
大数据·数据仓库·数据湖·湖仓一体
金伟API102414 小时前
常见的SQL面试题:经典50例
数据库·人工智能·笔记·sql·学习