神经网络数据库构建中3张数据表关联合并方法咨询
神经网络数据集三表合并实现方案
别自己写循环做匹配,不管是数据库层面还是数据处理库都有成熟的关联逻辑,性能和稳定性比手写遍历高很多,完全贴合你说的两步关联思路,直接用下面的方案就行。
方案1:数据库端直接用SQL实现(生产环境优先选)
关联前先确认两个时间戳字段的精度、时区一致,如果是设备采集类数据经常会存在毫秒级偏差,不要硬做等值匹配,按需加时间容差。
SELECT -- 必选:表1的2列additional data t1.`name of picture`, t1.additional_data_col1, t1.additional_data_col2, -- 可选保留字段 t2.`name of machine`, t2.`timestamp 1`, -- 必选:表3的7列additional prozess info t3.additional_prozess_col1, t3.additional_prozess_col2, t3.additional_prozess_col3, t3.additional_prozess_col4, t3.additional_prozess_col5, t3.additional_prozess_col6, t3.additional_prozess_col7 FROM table1 t1 -- 第一步:通过图片名关联表1、表2 INNER JOIN table2 t2 ON t1.`name of picture` = t2.`name of picture` -- 第二步:通过设备名+时间戳关联表3 INNER JOIN table3 t3 ON t2.`name of machine` = t3.`name of machine` -- 精确时间匹配用下面的等值条件 AND t2.`timestamp 1` = t3.`timestamp 2` -- 时间有偏差的话换成容差逻辑,比如允许前后1秒误差,按你用的数据库时间函数调整 -- AND ABS(TIMESTAMPDIFF(SECOND, t2.`timestamp 1`, t3.`timestamp 2`)) <= 1 ;
- 字段名带空格记得用对应数据库的转义符包裹:MySQL用反引号,PostgreSQL用双引号,SQL Server用方括号
- 关联逻辑按需选:
INNER JOIN只保留两边都匹配到的数据,LEFT JOIN会保留左表所有数据,没匹配到的字段填空值,根据你数据集构建的要求选就行 - 上面SELECT里列名我写了占位符,替换成你实际的列名就行,确保2列附加数据、7列流程信息必选,其他字段要不要留随意。
方案2:Python pandas做离线ETL(适合本地构建训练集场景)
手写循环效率极低,pandas内置的关联方法已经做了C层面的优化,处理百万级数据也很快。
import pandas as pd # 读取三张源表,支持从csv、数据库查询结果、excel等来源读取 df1 = pd.read_sql("SELECT * FROM table1", db_conn) # 表1 df2 = pd.read_sql("SELECT * FROM table2", db_conn) # 表2 df3 = pd.read_sql("SELECT * FROM table3", db_conn) # 表3 # 第一步:关联表1和表2,匹配字段为图片名 df_merge1 = pd.merge( left=df1, right=df2, on="name of picture", how="left" # 要过滤没匹配到设备的图片就换成inner ) # 第二步:关联表3,先统一时间戳字段名 df_merge1 = df_merge1.rename(columns={"timestamp 1": "ts"}) df3 = df3.rename(columns={"timestamp 2": "ts"}) # 精确时间匹配用普通merge df_final = pd.merge( left=df_merge1, right=df3, on=["name of machine", "ts"], how="left" # 要过滤没匹配到流程信息的数据就换成inner ) # 如果时间戳需要容差匹配,把上面的merge换成merge_asof,比如允许1秒内的时间差 # df_final = pd.merge_asof( # left=df_merge1.sort_values("ts"), # right=df3.sort_values("ts"), # on="ts", # by="name of machine", # tolerance=pd.Timedelta("1s"), # direction="nearest" # ) # 筛选需要保留的字段,导出最终数据集 keep_cols = [col for col in df1.columns if "additional data" in col] + \ [col for col in df3.columns if "additional prozess info" in col] + \ ["name of picture", "name of machine", "ts"] # 可选保留的字段 df_final = df_final[keep_cols] df_final.to_csv("nn_train_dataset.csv", index=False)
- 每一步merge之后打印下行数,比如
print(len(df_merge1), len(df_final)),如果行数掉的太多,先检查是不是有图片名、设备名的拼写错误、空值,或者时间戳精度不匹配(比如一个是秒级时间戳一个是毫秒级) - 时间字段提前转成pandas的datetime类型,避免数字类型的时间戳量级不匹配导致关联失败。
内容的提问来源于stack exchange,提问作者Lukas W
相关产品推荐
相关产品推荐

