Data Engineer / Data Scientist · DE / SQL

Meta 餐厅类型Top3 SQL:全体收入分母与Tie

按类型聚合净收入,取前三类型并算相对所有类型的收入占比。

题目重点:按类型聚合净收入,取前三类型并算相对所有类型的收入占比。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练Top3按completed net_revenue排名,不是订单数;exactly3 types、tie按type名称。题面“popular”若指订单数,要替换排名依据,不自动假定收入。
  • 每餐厅唯一type,一行一order;净收入与币种已统一,分母所有类型净收入而非前三之和。

解题路线

  1. 一个CTE按restaurant_type SUM收入,窗口SUM(revenue) OVER()在LIMIT之前计算全体类型总收入。最终ORDER BY revenue DESC,type LIMIT3,逻辑顺序保证分母未被Top3过滤。
  2. 如果先LIMIT3子查询再窗口sum,会把占比归一成前三内部份额,丢失对overall的比较;两者回答不同问题。
  3. exact3与包含并列第三名不同。需要包含tie则DENSE_RANK或RANK按明确政策,不能加type排序到rank里消除tie。
  4. cancelled排除,refund/gross/net若由独立事实提供先定义金额。总体净收入0用NULLIF返回NULL,负收入也可能使“份额”超常见0..1范围,需按财务口径解释。

手动走一遍

A/B/C/D收入40/30/20/10,前三占比0.4/0.3/0.2,总0.9,不是4/9、3/9、2/9。两类型同收入只取3时名称确定排序;含并列第三政策可能返回4行。

SQL 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

-- Training: top three TYPES by completed net revenue, not three individual restaurants.
-- Exact 3 rows (if available), ties broken type name. Share denominator ALL types.
WITH type_revenue AS (
 SELECT r.restaurant_type, SUM(o.net_revenue) AS revenue
 FROM orders o JOIN restaurant r ON r.restaurant_id=o.restaurant_id
 WHERE o.status='completed'
 GROUP BY r.restaurant_type
)
SELECT restaurant_type, revenue,
       1.0 * revenue / NULLIF(SUM(revenue) OVER (),0) AS overall_revenue_share
FROM type_revenue
ORDER BY revenue DESC, restaurant_type ASC
LIMIT 3;

复杂度

事实join/group需扫描O订单,T类型排序O(T log T),窗口总和O(T)。一个CTE足够表达粒度转换,但少CTE不等于计划一定更快,应按实际执行计划验证。

易错点与追问

容易失分的边界

  • 全体分母在LIMIT之后计算,百分比口径被偷换。
  • Top3餐厅与Top3类型混为一谈。

继续深挖

  • 如果每餐厅多type标签,是否全分配或按权重分配收入?需bridge表和计数政策。
  • 排名按订单数但占比按收入时,query要保存两个独立指标。
✓已复制微信号!