SQLazy:辨识组内差异来源于品牌还是型号
问题描述
库表 tbl 的 ID 字段是汽车分类,每个分类再细分为品牌(Brand)和型号(Type)。现在要按 ID 分组,判断该组内汽车的差异来源:如果该组有多个品牌,则 Difference 为 Brand;如果该组有多个型号,则 Difference 为 Type。同一个 ID 可能产生多条记录。
源数据
ID |
Brand |
Type |
1 |
Honda |
Coupe |
1 |
Jeep |
SUV |
2 |
Ford |
Sedan |
2 |
Ford |
Crossover |
期望结果
ID |
Difference |
1 |
Brand |
1 |
Type |
2 |
Type |
ID=1 有 Honda 和 Jeep 两个品牌,以及 Coupe 和 SUV 两个型号,因此 Difference 同时产生 Brand 和 Type 两条记录。
ID=2 只有 Ford 一个品牌,但有 Sedan 和 Crossover 两个型号,因此只产生 Type 一条记录。
SQLazy 分步实现
核心思路:先用 summarize 按 ID 分组统计不重复的品牌数(cntBrand)和型号数(cntType),然后用 expand 将统计结果与待判断的维度(“Brand” 和 “Type”)做叉乘,最后用 filter 筛选出满足条件的行。
Name |
Anchor |
Statement |
t1 |
tbl |
summarize Brand icount as cntBrand, Type icount as cntType; group ID |
t2 |
expand ["Brand","Type"] as Difference |
|
t3 |
filter (if ((Difference = "Brand") then cntBrand>1; (Difference = "Type") then cntType>1)) |
|
derive ID, Difference |
下面逐一解释这些步骤。
第 1 步:按 ID 分组统计不重复的品牌数和型号数
summarize Brand icount as cntBrand, Type icount as cntType; group ID
用 summarize 功能按 ID 分组,icount 函数统计组内不重复的 Brand 和 Type 数量,分别记为 cntBrand 和 cntType。这一步将每组明细数据压缩为每个 ID 一行,包含不重复计数。

第 2 步:将维度列表展开为行
expand ["Brand","Type"] as Difference
expand 功能将常量列表 ["Brand","Type"] 展开为行,与上一步每行做叉乘,生成新列 Difference。这样每个 ID 都会产生 Difference="Brand" 和 Difference="Type" 两条记录,同时保留 cntBrand 和 cntType 字段。

第 3 步:筛选满足条件的维度
filter (if ((Difference = "Brand") then cntBrand>1; (Difference = "Type") then cntType>1))
用 filter 功能配合条件分支语法,对 Difference="Brand" 的行筛选出 cntBrand>1 的记录,对 Difference="Type" 的行筛选出 cntType>1 的记录。

第 4 步:选取结果中需要的列
derive ID, Difference

编译生成 SQL
确认上述步骤后,SQLazy 编译器自动生成原生 SQL(PostgreSQL 语法):
WITH Value1 AS (
SELECT
ID,
COUNT(DISTINCT Brand) AS cntBrand,
COUNT(DISTINCT Type) AS cntType
FROM (
SELECT ID, Brand, Type FROM tbl
) tbl
GROUP BY ID
),
Value2 AS (
SELECT
Value1.ID, Value1.cntBrand, Value1.cntType, Difference
FROM Value1
CROSS JOIN (
SELECT 'Brand' AS Difference
UNION ALL
SELECT 'Type'
) T_1
)
SELECT ID, Difference FROM Value2
WHERE CASE
WHEN (Difference = 'Brand') THEN cntBrand > 1
WHEN (Difference = 'Type') THEN cntType > 1
ELSE NULL
END
SQLazy 让你用业务语言描述逻辑,而不是用 SQL 语法写嵌套查询。解题过程分 4 步,每步都可独立验证中间结果,降低了复杂逻辑的出错概率。summarize 功能的 icount 函数可以直接统计不重复值数量,一行代码替代 SQL 的 COUNT(DISTINCT ...)。expand 功能将常量列表展开为行,一行代码完成 SQL 中 CROSS JOIN 配合 UNION ALL 的多步操作。filter 功能的条件分支语法(if ... then ...; ... then ...)让多条件筛选逻辑一目了然,比 SQL 的 CASE WHEN 嵌套更清晰。
官方链接
SQLazy 在线体验:sqlazy.com(免费,无需注册)
SQLazy 项目仓库:github.com/SPLWare/SQLazy

英文版 https://c.esproc.com/article/1784205830591