分类映射函数 CASE 可以将多个数据列映射为一个新的列。映射时从第一个 WHEN 开始,按照每个 WHEN 中的条件对每行数据进行判断,一旦满足条件即输出对应的映射值,不再判断后面的 WHEN 或 ELSE。
将多列映射为表格时需保证每列中的数据类型一致;本函数所涉及的关键词大小写不敏感。
语法1:
case
when <condition1> then <projection1>
when <condition2> then <projection2>
...
else <other>
end
语法2:
case <expression>
when <value1> then <projection1>
when <value2> then <projection2>
...
else <other>
end
- <projectionN> 为数据满足条件 <conditionN>,或满足 <expression> 等于 <valueN> 时的映射表达式
- <other> 为不满足任何条件时的映射表达式,不填写 ELSE 语句则默认为 0、空字符串等
- 映射为点、边时取 UUID,映射为路径时取行号
当多个数据列非同源时,在 WITH 中使用该函数时会先将非同源列做笛卡尔乘积后再计算,在 RETURN 中使用该函数时会直接将各列截为等长后再计算。
映射为常量
示例:将顾客按照 80后、90后、00后、其他分为四个年龄段,并统计各年龄段的人数
find().nodes({@customer}) as nodes
with CASE
when year(nodes.birthday) <=> [1980, 1989] then "1980s"
when year(nodes.birthday) <=> [1990, 1999] then "1990s"
when year(nodes.birthday) <=> [2000, 2009] then "2000s"
else "others" END as ageGroup
group by ageGroup
return ageGroup, count(ageGroup)
示例:将上例用分类映射的简写格式进行改写
find().nodes({@customer}) as nodes
with CASE floor(year(nodes.birthday)/10)
when 198 then "1980s"
when 199 then "1990s"
when 200 then "2000s"
else "others" END as ageGroup
group by ageGroup
return ageGroup, count(ageGroup)
映射为函数值
示例:计算 2022 年每月的实际发薪日,已知每月 15 号为拟发薪日,如遇非工作日需顺延至下个星期一
uncollect ["2022-1-15 0:0:0","2022-2-15 0:0:0","2022-3-15 0:0:0","2022-4-15 0:0:0","2022-5-15 0:0:0","2022-6-15 0:0:0","2022-7-15 0:0:0","2022-8-15 0:0:0","2022-9-15 0:0:0","2022-10-15 0:0:0","2022-11-15 0:0:0","2022-12-15 0:0:0"] as plan
return CASE day_of_week(plan)
when 1 then date_add(plan, 1, "day")
when 7 then date_add(plan, 2, "day")
else date_add(plan, 0, "day")
END
分析:上面 CASE 函数中的第一个条件将拟发薪日为星期日的时间向后偏移一天,第二个条件将拟发薪日为星期六的时间向后偏移两天,ELSE 将其余时间偏移 0 天。注意,ELSE 后不能直接写 plan,因为 plan 的数据类型为字符串,date_add() 的函数值的数据类型为时间,为了保持数据类型一致需要将 plan 通过 date_add() 函数转为时间类型。
映射为别名
示例:为因银行卡 CA001、CA002、CA005 各查找一条向外转账的一步路径,将每条路径统计为 [<卡号>, <金额>, <收款卡ID>];如果路径不存在则统计为 [<卡号>, 0, "none"]
find().nodes({_id in ["CA001","CA002","CA005"]}) as cards
optional n(cards).le({@transfer} as e).n({@card} as n).limit(1)
return CASE n
when 0 then [cards._id, 0, "none"]
else [cards._id, e.amount, n._id] END
分析:1)使用 optional
时,其后的模板查询语句的某一次执行如果无结果,则该次执行返回一条伪路径 0-0-0;2)用 CASE 筛选出伪路径 0-0-0 并将其映射为 [<卡号>, 0, "none"],将其余路径映射为表格 [<卡号>, <金额>, <收款ID>],注意表格各列需要保持统一的数据类型。