
在数据分析和处理中,我们经常需要对数据进行排序。bigquery提供了标准的order by子句,支持按列的升序或降序排列。然而,有时我们需要更复杂的自定义排序逻辑,例如根据特定业务规则、字符串的自然语言顺序(忽略大小写和变音符号),或者基于非字母数字的自定义排名。本文将详细介绍在bigquery中实现这类自定义排序的两种主要方法:利用case语句构建排序键和使用javascript用户定义函数(udf)。
当自定义排序规则是预先定义且相对固定时,使用CASE语句创建临时的排序键是 BigQuery 中最推荐且性能最佳的方法。这种方法将每个需要排序的值映射到一个数值或具有明确顺序的字符串,然后根据这个映射值进行排序。
工作原理: 通过CASE表达式,您可以为每个特定的输入值指定一个对应的“排名”或“权重”。BigQuery会根据这些生成的排名值进行标准的数字或字符串排序,从而实现自定义的逻辑顺序。
示例场景: 假设我们有一个包含字符串值"date", "time", "number"的表,我们希望它们按照"number" -> "time" -> "date"的顺序进行排序。
WITH tbl AS (
SELECT "date" AS val UNION ALL
SELECT "time" UNION ALL
SELECT "number"
)
SELECT
tbl.val,
-- 使用CASE语句为每个值分配一个排序优先级
CASE tbl.val
WHEN 'number' THEN 1
WHEN 'time' THEN 2
WHEN 'date' THEN 3
ELSE 99 -- 处理未匹配的值,给予一个默认优先级
END AS sort_rank
FROM tbl
ORDER BY sort_rank;输出:
| val | sort_rank |
|---|---|
| number | 1 |
| time | 2 |
| date | 3 |
优点:
注意事项:
对于需要更复杂比较逻辑的场景,例如字符串的自然语言比较(如JavaScript的localeCompare)或基于动态规则的自定义排名函数,JavaScript UDF提供了一种解决方案。然而,由于其工作机制,此方法在处理大规模数据集时存在显著的性能限制。
工作原理: BigQuery的JavaScript UDF允许您在SQL查询中执行JavaScript代码。但是,与传统编程语言中直接传递比较函数给sort方法不同,BigQuery UDF不能直接接收两个元素进行比较。相反,它需要接收一个完整的数组,在UDF内部对这个数组进行排序,然后返回排序后的数组。之后,我们需要将原始数据与这个排序结果进行关联,以确定每个元素的最终排序位置。
示例场景: 沿用上面的例子,我们希望实现"number" -> "time" -> "date"的自定义排序,但这次通过一个JavaScript函数来定义排名映射。
-- 定义一个JavaScript UDF,用于对字符串数组进行自定义排序
CREATE TEMP FUNCTION sortme(MyValues ARRAY<STRING>)
RETURNS ARRAY<STRING>
LANGUAGE js AS
"""
// 定义自定义的排名映射
const RANK_MAP = {"number": 1, "time": 2, "date": 3};
// 自定义比较函数
function customCompare(val1, val2) {
// 如果值不在RANK_MAP中,可以给予一个默认排名,例如Infinity
const rank1 = RANK_MAP[val1] !== undefined ? RANK_MAP[val1] : Infinity;
const rank2 = RANK_MAP[val2] !== undefined ? RANK_MAP[val2] : Infinity;
return rank1 - rank2;
}
// 使用自定义比较函数对数组进行排序
MyValues.sort(customCompare);
return MyValues;
""";
-- 示例数据
WITH tbl AS (
SELECT "date" AS val UNION ALL
SELECT "time" UNION ALL
SELECT "number" UNION ALL
SELECT "apple" -- 添加一个不在RANK_MAP中的值
),
-- 步骤1: 聚合所有不重复的val值到一个数组中
helper AS (
SELECT sortme(ARRAY_AGG(DISTINCT val)) AS sorted_values FROM tbl
)
-- 步骤2: 将排序后的数组展开,并与原始表连接
SELECT
t.val,
-- 通过连接获取排序后的索引,作为最终的排序键
s.sort_by
FROM tbl AS t
LEFT JOIN (
SELECT
sorted_val,
sort_by -- sort_by是unnest生成的偏移量,即排序后的索引
FROM helper,
UNNEST(helper.sorted_values) AS sorted_val WITH OFFSET AS sort_by
) AS s
ON t.val = s.sorted_val
ORDER BY s.sort_by;输出:
| val | sort_by |
|---|---|
| number | 0 |
| time | 1 |
| date | 2 |
| apple | 3 |
解释:
优点:
注意事项:
在BigQuery中实现自定义排序时,应优先考虑以下策略:
通过选择合适的策略,您可以在BigQuery中有效地管理和实现各种自定义排序需求。
以上就是BigQuery中实现自定义排序:策略与实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号