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 确保聚合和计算都在订单级别。

Picture2png

第 2 步:选择最终输出列

derive ORDER_NUMBER, SKU, WEBSITE, FULFILLED_BY

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

Picture3png

编译生成 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 函数让 "集合成员检查" 像日常语言一样可读。分步计算让每一步的中间结果都可独立验证,降低了整体逻辑的出错概率。

官方链接

SQLazy 在线体验:sqlazy.com(免费,无需注册)
SQLazy 项目仓库:github.com/SPLWare/SQLazy