collect_list 和 collect_set 是大数据处理(如 Spark SQL 或 Hive)中常用的聚合函数,它们的主要区别在于:


✅ 1. collect_list

  • 作用:将某列的值按组收集成一个列表(有序),可以包含重复值
  • 语法示例SELECT dept, collect_list(name) AS employee_names FROM employees GROUP BY dept;
  • 结果特点
    • 有顺序(但不一定是插入顺序)
    • 可以有重复值
  • 示例:deptnameAAliceABobAAlice使用 collect_list(name) 的结果:A => [Alice, Bob, Alice]

✅ 2. collect_set

  • 作用:将某列的值按组收集成一个集合(无序),自动去重
  • 语法示例SELECT dept, collect_set(name) AS unique_employee_names FROM employees GROUP BY dept;
  • 结果特点
    • 无顺序(实现上可能有,但逻辑上不保证)
    • 自动去重
  • 示例:deptnameAAliceABobAAlice使用 collect_set(name) 的结果:A => [Alice, Bob]

📌 总结对比表:

特性collect_listcollect_set
是否去重❌ 否✅ 是
是否保留顺序✅ 是(不一定稳定)❌ 否(无序)
可包含重复值✅ 是❌ 否

👀 使用场景建议:

  • 如果你需要所有元素(包括重复)并且顺序有意义 → 用 collect_list
  • 如果你只关心唯一元素的集合 → 用 collect_set

好的!下面我用 PySpark 给你演示 collect_list 和 collect_set 的区别。


🧪 示例数据集

我们用一个简单的员工部门表:

namedept
AliceA
BobA
AliceA
CindyB
BobB
BobB

✅ PySpark 示例代码

from pyspark.sql import SparkSession
from pyspark.sql.functions import collect_list, collect_set

# 创建 SparkSession
spark = SparkSession.builder.appName("CollectExample").getOrCreate()

# 示例数据
data = [
    ("Alice", "A"),
    ("Bob", "A"),
    ("Alice", "A"),
    ("Cindy", "B"),
    ("Bob", "B"),
    ("Bob", "B")
]

# 创建 DataFrame
df = spark.createDataFrame(data, ["name", "dept"])

# 展示原始数据
print("原始数据:")
df.show()

# 使用 collect_list
df_list = df.groupBy("dept").agg(collect_list("name").alias("name_list"))

# 使用 collect_set
df_set = df.groupBy("dept").agg(collect_set("name").alias("name_set"))

# 展示 collect_list 结果
print("使用 collect_list:")
df_list.show(truncate=False)

# 展示 collect_set 结果
print("使用 collect_set:")
df_set.show(truncate=False)

🧾 输出结果示例(可能因顺序略有不同):

原始数据:

+-----+------+
|name |dept  |
+-----+------+
|Alice|A     |
|Bob  |A     |
|Alice|A     |
|Cindy|B     |
|Bob  |B     |
|Bob  |B     |
+-----+------+

使用 collect_list

+-----+--------------------+
|dept |name_list           |
+-----+--------------------+
|A    |[Alice, Bob, Alice] |
|B    |[Cindy, Bob, Bob]   |
+-----+--------------------+

使用 collect_set

+-----+----------------+
|dept |name_set        |
+-----+----------------+
|A    |[Alice, Bob]    |
|B    |[Cindy, Bob]    |
+-----+----------------+

🎯 总结

  • collect_list:保留了重复值,比如 A 部门中出现了两个 Alice
  • collect_set:去重后的结果,比如 B 部门中只有一个 Bob