跳到主要内容

华为大数据面试SQL-供应链库存周转天数计算

一、题目

已知有三张表:

  • t1_product_info:产品信息表(product_id, product_name, category)
  • t1_daily_inventory:每日库存快照表(product_id, snapshot_date, inventory_qty)
  • t1_daily_sales:每日销售明细表(product_id, sale_date, sale_qty)

库存周转天数 = 统计周期内的平均库存量 / 日均销售量。请计算2024年6月每个产品的库存周转天数,结果保留两位小数,按周转天数升序排列。

其中:

  • 平均库存量 = 每日库存量之和 / 统计天数
  • 日均销售量 = 总销售量 / 统计天数

样例数据

t1_product_info:

+------------+---------------+------------+
| product_id | product_name | category |
+------------+---------------+------------+
| P001 | 交换机A型 | 网络设备 |
| P002 | 服务器B型 | 计算设备 |
| P003 | 光模块C型 | 光传输 |
+------------+---------------+------------+

t1_daily_inventory:

+------------+---------------+---------------+
| product_id | snapshot_date | inventory_qty |
+------------+---------------+---------------+
| P001 | 2024-06-01 | 500 |
| P001 | 2024-06-02 | 480 |
| P001 | 2024-06-03 | 450 |
| P002 | 2024-06-01 | 1200 |
| P002 | 2024-06-02 | 1150 |
| P002 | 2024-06-03 | 1100 |
| P003 | 2024-06-01 | 800 |
| P003 | 2024-06-02 | 780 |
| P003 | 2024-06-03 | 760 |
+------------+---------------+---------------+

t1_daily_sales:

+------------+------------+----------+
| product_id | sale_date | sale_qty |
+------------+------------+----------+
| P001 | 2024-06-01 | 30 |
| P001 | 2024-06-02 | 25 |
| P001 | 2024-06-03 | 35 |
| P002 | 2024-06-01 | 60 |
| P002 | 2024-06-02 | 55 |
| P002 | 2024-06-03 | 65 |
| P003 | 2024-06-01 | 20 |
| P003 | 2024-06-02 | 25 |
| P003 | 2024-06-03 | 15 |
+------------+------------+----------+

三、思路分析

本题是供应链管理中的经典KPI计算,公式清晰但需要注意数据对齐:

  • 分别聚合库存和销售:先按product_id分别统计6月份的总库存量(或日均库存量)和总销售量(或日均销售量)。使用SUM和COUNT可以获得计算所需的分子分母。

  • 注意数据完整性:如果某个产品在6月份某天没有库存快照或没有销售记录,COUNT的天数会不同。需要统一用30天(6月天数)还是用实际有数据的天数作为分母——本题使用实际有数据的快照天数。

  • 计算公式周转天数 = (sum(inventory_qty)/count(distinct snapshot_date)) / (sum(sale_qty)/count(distinct sale_date)) = avg_daily_inventory / avg_daily_sales

库存周转天数是华为供应链管理中的核心指标,天数越短说明产品周转越快、资金占用越少、运营效率越高。

维度评分
题目难度⭐️⭐️⭐️
题目清晰度⭐️⭐️⭐️⭐️⭐️
业务常见度⭐️⭐️⭐️⭐️⭐️

四、逐步推导

1.分别计算每个产品的日均库存和日均销量

对库存表和销售表分别按product_id聚合,计算总和及天数,然后得到日均值。

执行SQL

select
inv.product_id,
sum(inv.inventory_qty) as total_inventory,
count(distinct inv.snapshot_date) as inv_days,
round(sum(inv.inventory_qty) * 1.0 / count(distinct inv.snapshot_date), 2) as avg_inventory
from t1_daily_inventory inv
where inv.snapshot_date >= '2024-06-01' and inv.snapshot_date <= '2024-06-30'
group by inv.product_id

执行结果

+------------+-----------------+----------+---------------+
| product_id | total_inventory | inv_days | avg_inventory |
+------------+-----------------+----------+---------------+
| P001 | 1430 | 3 | 476.67 |
| P002 | 3450 | 3 | 1150.00 |
| P003 | 2340 | 3 | 780.00 |
+------------+-----------------+----------+---------------+

2.计算日均销量

执行SQL

select
product_id,
sum(sale_qty) as total_sales,
count(distinct sale_date) as sale_days,
round(sum(sale_qty) * 1.0 / count(distinct sale_date), 2) as avg_daily_sales
from t1_daily_sales
where sale_date >= '2024-06-01' and sale_date <= '2024-06-30'
group by product_id

执行结果

+------------+-------------+-----------+------------------+
| product_id | total_sales | sale_days | avg_daily_sales |
+------------+-------------+-----------+------------------+
| P001 | 90 | 3 | 30.00 |
| P002 | 180 | 3 | 60.00 |
| P003 | 60 | 3 | 20.00 |
+------------+-------------+-----------+------------------+

3.关联产品信息,计算库存周转天数

将库存和销售的结果与产品信息表关联,计算周转天数 = 日均库存 / 日均销量。

执行SQL

with avg_inv as (
select
product_id,
round(sum(inventory_qty) * 1.0 / count(distinct snapshot_date), 2) as avg_daily_inventory
from t1_daily_inventory
where snapshot_date >= '2024-06-01' and snapshot_date <= '2024-06-30'
group by product_id
),
avg_sale as (
select
product_id,
round(sum(sale_qty) * 1.0 / count(distinct sale_date), 2) as avg_daily_sales
from t1_daily_sales
where sale_date >= '2024-06-01' and sale_date <= '2024-06-30'
group by product_id
)
select
p.product_id,
p.product_name,
p.category,
coalesce(i.avg_daily_inventory, 0) as avg_daily_inventory,
coalesce(s.avg_daily_sales, 0) as avg_daily_sales,
case
when coalesce(s.avg_daily_sales, 0) = 0 then null
else round(i.avg_daily_inventory / s.avg_daily_sales, 2)
end as turnover_days
from t1_product_info p
left join avg_inv i on p.product_id = i.product_id
left join avg_sale s on p.product_id = s.product_id
order by turnover_days

执行结果

+------------+---------------+------------+---------------------+------------------+----------------+
| product_id | product_name | category | avg_daily_inventory | avg_daily_sales | turnover_days |
+------------+---------------+------------+---------------------+------------------+----------------+
| P003 | 光模块C型 | 光传输 | 780.00 | 20.00 | 39.00 |
| P001 | 交换机A型 | 网络设备 | 476.67 | 30.00 | 15.89 |
| P002 | 服务器B型 | 计算设备 | 1150.00 | 60.00 | 19.17 |
+------------+---------------+------------+---------------------+------------------+----------------+

分析:交换机A型(P001)周转天数最短(15.89天),说明该产品动销最快、库存效率最高;光模块C型(P003)周转天数最长(39天),可能需要关注库存积压风险。

五、常见坑点

坑1:NULL值的隐式处理 — 聚合函数跳过NULL,窗口函数不跳过。WHERE需显式过滤或用COALESCE替代。

坑2:数据类型不一致导致JOIN失效 — string vs int隐式转换可能触发全表扫描,性能骤降。

六、举一反三

  1. 增加时间维度对比:按天/周/月分组,观察指标的趋势和季节性波动

  2. 增加分组维度:按品类/地区/渠道拆解,发现差异化的业务洞察

  3. 设置预警阈值:在WHERE中加阈值判断,自动筛选异常数据

七、知识点总结

考点说明
多表JOINLEFT JOIN保留主表所有数据,COALESCE处理NULL
GROUP BY + 聚合函数分组聚合是数据分析的基础,配合HAVING筛选分组结果
日期函数DATEDIFF / DATE_ADD / unix_timestamp处理日期运算
NULL值处理NULL在聚合和窗口函数中的差异,COALESCE/NVL的替代方案

八、建表语句和数据插入

点击展开 DDL & DML
--建表语句
CREATE TABLE IF NOT EXISTS t1_product_info (
product_id STRING COMMENT '产品ID',
product_name STRING COMMENT '产品名称',
category STRING COMMENT '产品类别'
);

CREATE TABLE IF NOT EXISTS t1_daily_inventory (
product_id STRING COMMENT '产品ID',
snapshot_date STRING COMMENT '库存快照日期',
inventory_qty BIGINT COMMENT '当日库存量'
);

CREATE TABLE IF NOT EXISTS t1_daily_sales (
product_id STRING COMMENT '产品ID',
sale_date STRING COMMENT '销售日期',
sale_qty BIGINT COMMENT '当日销售量'
);

--数据插入
INSERT INTO t1_product_info(product_id, product_name, category) VALUES
('P001', '交换机A型', '网络设备'),
('P002', '服务器B型', '计算设备'),
('P003', '光模块C型', '光传输');

INSERT INTO t1_daily_inventory(product_id, snapshot_date, inventory_qty) VALUES
('P001', '2024-06-01', 500),
('P001', '2024-06-02', 480),
('P001', '2024-06-03', 450),
('P002', '2024-06-01', 1200),
('P002', '2024-06-02', 1150),
('P002', '2024-06-03', 1100),
('P003', '2024-06-01', 800),
('P003', '2024-06-02', 780),
('P003', '2024-06-03', 760);

INSERT INTO t1_daily_sales(product_id, sale_date, sale_qty) VALUES
('P001', '2024-06-01', 30),
('P001', '2024-06-02', 25),
('P001', '2024-06-03', 35),
('P002', '2024-06-01', 60),
('P002', '2024-06-02', 55),
('P002', '2024-06-03', 65),
('P003', '2024-06-01', 20),
('P003', '2024-06-02', 25),
('P003', '2024-06-03', 15);
📱关注公众号

「数据仓库技术」文章同步更新,不错过每一篇干货

微信公众号二维码
💬加群交流

备注「数据仓库技术」加入社群,每日一道大厂SQL真题

交流微信二维码

你可能还想看