如何实现数据表中多字段关联行的全量查询?
问题描述
给定如下数据表:
| id | user_id | phone_number | email | | -------- | -------- | ------------ | --------------- | | 1 | 999 | 61412308310 |can@gmail.com | | 2 | 129 | 61477708777 |acdc@gmail.com | | 3 | 213 | 61488908495 |adel99@gmail.com | | 4 | 145 | 61477708777 |austr@gmail.com | | 5 | 214 | 61421445777 |austr@gmail.com | | 6 | 214 | 61421445326 |jango@gmail.com |
需求:输入该数据集中user_id、phone_number、email任意一列的某个值,查询所有存在关联的行(包括间接关联)。
示例:当输入phone_number = 61477708777时,预期结果为:
| id | user_id | phone_number | email | | -------- | -------- | ------------ | --------------- | | 2 | 129 | 61477708777 |acdc@gmail.com | | 4 | 145 | 61477708777 |austr@gmail.com | | 5 | 214 | 61421445777 |austr@gmail.com | | 6 | 214 | 61421445326 |jango@gmail.com |
关联逻辑:
- id=2和id=4直接匹配查询条件;
- id=5与id=4共享相同email;
- id=6与id=5共享相同user_id;
以上所有关联行都需要被检索出来。
现有函数仅能匹配直接符合条件的行,无法处理间接关联:
def search_data(field, value, data): data_dict = {} for row in data: key = row[field] if key not in data_dict: data_dict[key] = [] data_dict[key].append(row) return data_dict.get(value, [])
解决方案
这个问题本质是图的连通分量查找:把每一行看作一个节点,只要两行共享user_id、phone_number或email中的任意一个值,就认为它们之间有连接。我们需要找出与初始节点直接或间接连通的所有节点。
实现步骤
- 为三个字段分别建立索引:记录每个字段值对应的所有行,方便快速查找关联行。
- 使用广度优先搜索(BFS)或深度优先搜索(DFS),从初始匹配的行出发,不断扩展所有关联行,直到没有新的行加入。
- 去重:用行的
id作为唯一标识,避免重复处理同一行。
代码实现
def find_related_rows(field, value, data): # 建立三个字段的索引:字段值 -> 对应的行列表 indexes = { 'user_id': {}, 'phone_number': {}, 'email': {} } for row in data: for idx_field in indexes: key = row[idx_field] if key not in indexes[idx_field]: indexes[idx_field][key] = [] indexes[idx_field][key].append(row) # 获取初始匹配的行 initial_rows = indexes[field].get(value, []) if not initial_rows: return [] # BFS遍历所有关联行 visited_ids = set() queue = [] # 初始化队列和已访问集合 for row in initial_rows: if row['id'] not in visited_ids: visited_ids.add(row['id']) queue.append(row) while queue: current_row = queue.pop(0) # 改用pop()即为DFS遍历 # 遍历当前行的三个字段,查找关联行 for idx_field in indexes: key = current_row[idx_field] for related_row in indexes[idx_field].get(key, []): if related_row['id'] not in visited_ids: visited_ids.add(related_row['id']) queue.append(related_row) # 返回按id排序的结果 return sorted([row for row in data if row['id'] in visited_ids], key=lambda x: x['id'])
测试示例
假设数据以字典列表形式存储:
data = [ {'id': 1, 'user_id': 999, 'phone_number': '61412308310', 'email': 'can@gmail.com'}, {'id': 2, 'user_id': 129, 'phone_number': '61477708777', 'email': 'acdc@gmail.com'}, {'id': 3, 'user_id': 213, 'phone_number': '61488908495', 'email': 'adel99@gmail.com'}, {'id': 4, 'user_id': 145, 'phone_number': '61477708777', 'email': 'austr@gmail.com'}, {'id': 5, 'user_id': 214, 'phone_number': '61421445777', 'email': 'austr@gmail.com'}, {'id': 6, 'user_id': 214, 'phone_number': '61421445326', 'email': 'jango@gmail.com'}, ] # 查询phone_number=61477708777的关联行 result = find_related_rows('phone_number', '61477708777', data) # 打印结果表格 print("| id | user_id | phone_number | email |") print("| -------- | -------- | ------------ | --------------- |") for row in result: print(f"| {row['id']:<8} | {row['user_id']:<8} | {row['phone_number']:<12} | {row['email']:<15} |")
运行后会输出符合预期的结果。
说明
- 索引的建立避免了每次查找都遍历整个数据集,提升了查询效率。
- BFS/DFS确保能覆盖所有直接和间接关联的行,不会遗漏。
- 用
id作为唯一标识去重,避免重复处理同一行。
内容的提问来源于stack exchange,提问作者wdad asd
相关产品推荐
相关产品推荐

