PySpark中对40位超大数字字符串列排序的实现方案
解决PySpark超大数字字符串列的正确排序问题
核心思路
无法将超过38位的数字转为Decimal类型,且直接按字符串字典序排序会得到错误结果(首字符优先级高于长度),可利用正数字符串的数值大小规律实现正确排序:
- 位数更长的数字数值一定更大
- 位数相同时,字符串的字典序与数值大小顺序一致
因此排序逻辑改为:先按字符串长度降序,再按字符串本身降序。
方法一:Spark SQL实现
修改SQL语句的排序规则:
from pyspark.sql import Row product_updates = [ {'product_id': '00001', 'product_name': 'Heater', 'price': '1111111111111111111111111111111111111111', 'category': 'Electronics'}, {'product_id': '00006', 'product_name': 'Chair', 'price': '50', 'category': 'Furniture'}, {'product_id': '00007', 'product_name': 'Desk', 'price': '60', 'category': 'Furniture'} ] df_product_updates = spark.createDataFrame(Row(**x) for x in product_updates) df_product_updates.createOrReplaceTempView("sort_price") df_sort_price = spark.sql(f""" select *, row_number() over (order by length(price) DESC, price DESC) rn from sort_price """) df_sort_price.show(truncate=False)
正确排序结果
+----------+------------+----------------------------------------+-----------+---+ |product_id|product_name|price |category |rn | +----------+------------+----------------------------------------+-----------+---+ |00001 |Heater |1111111111111111111111111111111111111111|Electronics|1 | |00007 |Desk |60 |Furniture |2 | |00006 |Chair |50 |Furniture |3 | +----------+------------+----------------------------------------+-----------+---+
方法二:DataFrame API实现
若习惯链式调用写法,可使用DataFrame API:
from pyspark.sql.functions import length, row_number from pyspark.sql.window import Window window_spec = Window.orderBy(length("price").desc(), "price".desc()) df_sort_price = df_product_updates.withColumn("rn", row_number().over(window_spec)) df_sort_price.show(truncate=False)
扩展:处理负数场景
如果price包含负数,需额外处理符号逻辑:
- 先按符号排序(按需决定负数/正数在前)
- 正数按「长度降序+字符串降序」排序
- 负数按「长度升序+字符串升序」排序(位数更长的负数数值更小)
示例SQL逻辑:
select *, row_number() over ( order by case when price like '-%' then 0 else 1 end, case when price like '-%' then length(price) else -length(price) end, price ) rn from sort_price
内容的提问来源于stack exchange,提问作者user1668814
相关产品推荐
相关产品推荐

