You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python/Pandas将SQL联表结果转为三层嵌套字典?

高效实现扁平数据的嵌套分组转换

我从三表关联的SQL存储过程中得到了如下扁平数据:

data = [
    {"so_number": "ABC", "po_status": "OPEN", "item_id": 0, "part_number": "XTZ", "ticket_id": 10, "ticket_month": "JUNE"},
    {"so_number": "ABC", "po_status": "OPEN", "item_id": 0, "part_number": "XTZ", "ticket_id": 11, "ticket_month": "JUNE"},
    {"so_number": "ABC", "po_status": "OPEN", "item_id": 1, "part_number": "XTY", "ticket_id": 12, "ticket_month": "JUNE"},
    {"so_number": "DEF", "po_status": "OPEN", "item_id": 3, "part_number": "XTU", "ticket_id": 13, "ticket_month": "JUNE"},
    {"so_number": "DEF", "po_status": "OPEN", "item_id": 3, "part_number": "XTU", "ticket_id": 14, "ticket_month": "JUNE"},
    {"so_number": "DEF", "po_status": "OPEN", "item_id": 3, "part_number": "XTU", "ticket_id": 15, "ticket_month": "JUNE"}
]

需要按so_number和item_id分组,转换成如下嵌套结构的字典列表:

[
  {
    "so_number": "ABC",
    "po_status": "OPEN",
    "line_items": [
      {
        "item_id": 0,
        "part_number": "XTZ",
        "tickets": [
          {"ticket_id": 10, "ticket_month": "JUNE"},
          {"ticket_id": 11, "ticket_month": "JUNE"}
        ]
      },
      {
        "item_id": 1,
        "part_number": "XTY",
        "tickets": [{"ticket_id": 12, "ticket_month": "JUNE"}]
      }
    ]
  },
  {
    "so_number": "DEF",
    "po_status": "OPEN",
    "line_items": [
      {
        "item_id": 3,
        "part_number": "XTU",
        "tickets": [
          {"ticket_id": 13, "ticket_month": "JUNE"},
          {"ticket_id": 14, "ticket_month": "JUNE"},
          {"ticket_id": 15, "ticket_month": "JUNE"}
        ]
      }
    ]
  }
]

不想通过循环访问三张SQL表来生成(效率低且非最佳实践),求高效实现方式(可使用Pandas)。


一、原生Python实现(无需第三方库)

核心思路是用字典做分组容器,一次遍历完成多层分组,时间复杂度O(n),效率很高。

def transform_data(data):
    so_map = {}
    for row in data:
        so_num = row["so_number"]
        # 处理SO层级
        if so_num not in so_map:
            so_map[so_num] = {
                "so_number": so_num,
                "po_status": row["po_status"],
                "line_items": {}
            }
        so_entry = so_map[so_num]
        
        item_id = row["item_id"]
        # 处理item层级
        if item_id not in so_entry["line_items"]:
            so_entry["line_items"][item_id] = {
                "item_id": item_id,
                "part_number": row["part_number"],
                "tickets": []
            }
        item_entry = so_entry["line_items"][item_id]
        
        # 添加ticket
        item_entry["tickets"].append({
            "ticket_id": row["ticket_id"],
            "ticket_month": row["ticket_month"]
        })
    
    # 把line_items的字典转成列表
    result = []
    for so_entry in so_map.values():
        so_entry["line_items"] = list(so_entry["line_items"].values())
        result.append(so_entry)
    return result

# 调用示例
output = transform_data(data)
print(output)

二、Pandas实现(适合大数据量场景)

利用Pandas的groupby和聚合函数,结合to_dict完成转换,代码更简洁,处理大规模数据时性能更优。

import pandas as pd

df = pd.DataFrame(data)

# 先按so_number和item_id分组,聚合ticket数据
agg_result = df.groupby(["so_number", "po_status", "item_id", "part_number"]).apply(
    lambda x: x[["ticket_id", "ticket_month"]].to_dict("records")
).reset_index(name="tickets")

# 再按so_number和po_status分组,聚合line_items数据
final_result = agg_result.groupby(["so_number", "po_status"]).apply(
    lambda x: x[["item_id", "part_number", "tickets"]].to_dict("records")
).reset_index(name="line_items")

# 转换为目标字典列表
output = final_result.to_dict("records")
print(output)

内容的提问来源于stack exchange,提问作者Masterstack8080

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 03:01:00