PostgreSQL多表关联查询求助:按规则分配AdSpend至销售数据
PostgreSQL按销量占比分配广告费用的正确查询方案
需求说明
需关联SalesData、AdsData与PlatformMapping三张表,实现:
- 基于
Date和PlatformId维度,通过PlatformMapping的PlatformCode匹配AdsData的AdSpend - 将当日该
PlatformId下的总AdSpend,按每条SalesData记录的UnitsSold占比分配到对应记录中
各表结构与数据
Table1: SalesData
| Date | PlatformId | UnitsSold | Revenue | ChannelId |
|---|---|---|---|---|
| 2024-07-01 | ABCD1 | 12 | 1200 | 1 |
| 2024-07-02 | ABCD1 | 11 | 1000 | 1 |
| 2024-07-01 | ABCD2 | 4 | 1200 | 2 |
| 2024-07-03 | ABCD3 | 42 | 9000 | 3 |
| 2024-07-03 | ABCD3 | 10 | 1000 | 2 |
Table2: AdsData
| Date | PlatformCode | AdSpend |
|---|---|---|
| 2024-07-01 | 1A | 1000 |
| 2024-07-02 | 1A | 1500 |
| 2024-07-01 | 2B | 4000 |
| 2024-07-03 | 3C | 4200 |
Table3: PlatformMapping
| PlatformId | Platformcode |
|---|---|
| ABCD1 | 1A |
| ABCD2 | 2B |
| ABCD3 | 3C |
预期输出(Table4)
| Date | PlatformId | UnitsSold | Revenue | ChannelId | AdSpend |
|---|---|---|---|---|---|
| 2024-07-01 | ABCD1 | 12 | 1200 | 1 | 1000 |
| 2024-07-02 | ABCD1 | 11 | 1000 | 1 | 1500 |
| 2024-07-01 | ABCD2 | 4 | 1200 | 2 | 4000 |
| 2024-07-03 | ABCD3 | 32 | 9000 | 3 | 3200 |
| 2024-07-03 | ABCD3 | 10 | 1000 | 2 | 1000 |
注:预期输出中ABCD3第一条记录的UnitsSold应为32(与总AdSpend分配逻辑匹配),推测为输入笔误,以下查询按占比分配的核心逻辑实现
原查询问题分析
你的CTE查询存在两处关键错误:
AdSpendMapped未包含Revenue和ChannelId字段,最终查询无法输出这些必要列- 计算AdSpend时引用了未定义的
a.totalquantitysold字段,属于无效引用
正确PostgreSQL查询方案
使用窗口函数直接计算当日每个PlatformId的总销量,无需额外CTE,逻辑简洁高效:
SELECT sd.Date, sd.PlatformId, sd.UnitsSold, sd.Revenue, sd.ChannelId, -- 按销量占比分配广告费用,处理除数为0的异常情况 COALESCE( (ads.AdSpend * sd.UnitsSold) / NULLIF(SUM(sd.UnitsSold) OVER (PARTITION BY sd.Date, sd.PlatformId), 0), 0 )::INT AS AdSpend FROM SalesData sd -- 通过映射表关联广告表,确保日期与平台编码匹配 JOIN PlatformMapping pm ON sd.PlatformId = pm.PlatformId JOIN AdsData ads ON pm.Platformcode = ads.PlatformCode AND sd.Date = ads.Date ORDER BY sd.Date, sd.PlatformId, sd.ChannelId;
查询逻辑说明
- 表关联:SalesData通过PlatformMapping与AdsData按日期、平台编码关联,获取对应维度的总广告费用
- 窗口函数计算总销量:
SUM(sd.UnitsSold) OVER (PARTITION BY sd.Date, sd.PlatformId)计算当日当前PlatformId下的总UnitsSold - 占比分配:单条记录的UnitsSold除以总销量,再乘以总AdSpend,得到该记录应分配的广告费用
- 异常处理:用
NULLIF和COALESCE处理总销量为0的情况,避免除以0错误,此时AdSpend设为0 - 类型转换:用
::INT将计算结果转为整数,匹配预期输出格式
内容的提问来源于stack exchange,提问作者Shishank
相关产品推荐
相关产品推荐

