SQLazy: 按订单 SKU 条件分配仓库

问题描述

订单明细表记录了每笔订单的 ORDER_NUMBER、SKU 和 WEBSITE。现在需要按整单判断:如果同一订单中存在 SKU 为 10000 或 20000 的行,或者网站不是 EU SITE,则整单所有行分配 WAREHOUSE 1;否则分配 WAREHOUSE 2。新增字段 FULFILLED_BY。

源数据

|--------------|-------|---------|
| ORDER_NUMBER | SKU | WEBSITE |
| 10001 | 10000 | EU SITE |
| 10001 | 15123 | EU SITE |
| 10002 | 20000 | EU SITE |
| 10002 | 28467 | EU SITE |
| 10003 | 15123 | EU SITE |
| 10003 | 15124 | EU SITE |
| 10004 | 10000 | US SITE |
| 10005 | 15123 | US SITE |
| 10006 | 10000 | EU SITE |
| 10007 | 28467 | EU SITE |

期望结果

|--------------|-------|---------|--------------|
| ORDER_NUMBER | SKU | WEBSITE | FULFILLED_BY |
| 10001 | 10000 | EU SITE | WAREHOUSE 1 |
| 10001 | 15123 | EU SITE | WAREHOUSE 1 |
| 10002 | 20000 | EU SITE | WAREHOUSE 1 |
| 10002 | 28467 | EU SITE | WAREHOUSE 1 |
| 10003 | 15123 | EU SITE | WAREHOUSE 2 |
| 10003 | 15124 | EU SITE | WAREHOUSE 2 |
| 10004 | 10000 | US SITE | WAREHOUSE 1 |
| 10005 | 15123 | US SITE | WAREHOUSE 1 |
| 10006 | 10000 | EU SITE | WAREHOUSE 1 |
| 10007 | 28467 | EU SITE | WAREHOUSE 2 |

以几个有代表性的订单为例:

订单 10001、10002:包含特殊 SKU 10000 或 20000,整单分配 WAREHOUSE 1。

订单 10003:均为 EU SITE 且不含特殊 SKU,整单分配 WAREHOUSE 2。

订单 10004、10005:网站为 US SITE(非 EU),整单分配 WAREHOUSE 1。订单 10007:单行订单,非特殊 SKU,EU 站点,分配 WAREHOUSE 2。

SQLazy 分步实现

**核心思路:**按订单分组,用 compute 的 max 聚合判断订单中是否存在特殊 SKU,再根据聚合结果和 WEBSITE 条件,在同一个 compute 中计算出整单的 FULFILLED_BY。

|------|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Name | Anchor | Statement |
| t1 | tb_detail | compute if ((10000,20000 contain SKU)then 1 else 0) max as order_has_special; if (order_has_special = 1 or WEBSITE <> "EU SITE" then "WAREHOUSE 1" else "WAREHOUSE 2") as FULFILLED_BY; partition ORDER_NUMBER |
| | | derive ORDER_NUMBER, SKU, WEBSITE, FULFILLED_BY |

下面逐一解释这些步骤。

第 1 步:按订单分组计算分配仓库(核心)

compute if ((10000,20000 contain SKU)then 1 else 0) max as order_has_special; if (order_has_special = 1 or WEBSITE <> "EU SITE" then "WAREHOUSE 1" else "WAREHOUSE 2") as FULFILLED_BY; partition ORDER_NUMBER

这是核心的一步。一个 compute 语句中计算了两个字段:order_has_special,对订单内的每一行判断 SKU 是否在列表 10000,20000 中,用 contain 做集合成员检查,再以 max 聚合到订单级别------只要订单中任意一行命中,max 结果就是 1。 FULFILLED_BY:利用上一步的聚合结果,当 order_has_special=1 或 WEBSITE 不是 EU SITE 时分配 WAREHOUSE 1,否则分配 WAREHOUSE 2。partition ORDER_NUMBER 确保聚合和计算都在订单级别。

第 2 步:选择最终输出列

derive ORDER_NUMBER, SKU, WEBSITE, FULFILLED_BY

用 derive 保留需要的四列,去掉辅助字段 order_has_special,输出最终结果。

编译生成 SQL

确认上述步骤后,SQLazy 编译器自动生成原生 SQL(Snowflake 语法):

复制代码
WITH tb_detail_1 AS (
    SELECT ORDER_NUMBER, SKU, WEBSITE
        , MAX(CASE
            WHEN SKU IN (10000, 20000) THEN 1
            ELSE 0
        END) OVER (PARTITION BY ORDER_NUMBER) AS order_has_special
    FROM tb_detail
),
t1 AS (
    SELECT ORDER_NUMBER, SKU, WEBSITE, order_has_special
        , CASE
            WHEN order_has_special = 1
                OR WEBSITE <> 'EU SITE'
            THEN 'WAREHOUSE 1'
            ELSE 'WAREHOUSE 2'
        END AS FULFILLED_BY
    FROM tb_detail_1
)
SELECT ORDER_NUMBER, SKU, WEBSITE, FULFILLED_BY
FROM t1

SQLazy 让你用业务语言描述逻辑,而不是用 SQL 语法写嵌套查询。这个例子用 compute 语句完成 "先按订单聚合出标记、再基于标记分配" 的两层逻辑,无需像 SQL 那样先写一个 CTE 做 MAX(CASE WHEN ... IN ...) OVER 窗口聚合,再写另一个 CTE 做 CASE WHEN 判断。compute 的 partition 子句将 "订单级计算" 的语义直接表达出来,contain 函数让 "集合成员检查" 像日常语言一样可读。分步计算让每一步的中间结果都可独立验证,降低了整体逻辑的出错概率。

相关推荐
geovindu1 小时前
sql: Data Modeling Patterns using mysql
sql·mysql·设计模式·数据库开发
这个DBA有点耶2 小时前
AI Agent操作数据库的安全边界:只读沙箱、操作预演与自动回滚如何落地?
数据库·sql·程序人生·aigc·数据库架构·dba
Gl�ria3 小时前
Hive SQL 执行卡住完整排查 & 处理
hive·hadoop·sql
xcLeigh13 小时前
让大模型长出手脚,自己写SQL查数据库(Function Calling初探)
数据库·人工智能·sql·时序数据库·timechoai
2601_9626802218 小时前
数据分析面试常考的SQL题和业务题分别是哪几类?
sql·面试·数据分析
子非鱼a20 小时前
【SQL注入】 ShadowCart
sql
程序员阿鹏21 小时前
如何实现MySQL分库分表?
数据结构·数据库·sql·mysql·缓存
liangsheng_g1 天前
Spring事务传播行为分派与挂起恢复源码实战
数据库·sql·spring
杨云龙UP1 天前
MySQL Host is blocked because of many connection errors 导致 JDBC 连接失败排查与解决
linux·运维·网络·数据库·sql·mysql·登录失败