MySQL多列匹配:WHERE NOT IN子句中使用SELECT查询
高效检查房间-楼宇组合并新增记录的方案
我明白你的场景:手里有一批分属不同楼宇的房间数据(比如洗衣房(A楼1层)、102公寓(A楼1层)这类),日常需要验证新收到的房间/楼宇组合是否已经在数据库里,以此判断要不要新增记录,而且你已经搞定了把电子表格数据导入临时表的操作——这步很关键,接下来咱们可以用两种思路来完成后续的核心逻辑:
一、纯SQL方案(适合数据库端直接处理)
1. 先拆分字段(可选但强烈推荐)
如果你的临时表里存的是洗衣房(A楼1层)这种合并文本,建议先拆成独立的房间名称、楼宇、楼层字段,避免因为文本格式(比如全角/半角括号、空格差异)导致误判。以MySQL为例:
-- 先给临时表加字段 ALTER TABLE temp_rooms ADD COLUMN room_name VARCHAR(100), ADD COLUMN building VARCHAR(20), ADD COLUMN floor VARCHAR(20); -- 拆分文本内容 UPDATE temp_rooms SET room_name = SUBSTRING_INDEX(room_info, '(', 1), building = SUBSTRING_INDEX(SUBSTRING_INDEX(room_info, '(', -1), '楼', 1), floor = SUBSTRING_INDEX(SUBSTRING_INDEX(room_info, '楼', -1), ')', 1);
要是你的原始数据已经是拆分好的字段,直接跳过这步就行
2. 一键完成检查+插入
用INSERT ... SELECT ... WHERE NOT EXISTS的语法,直接从临时表往正式表插入不存在的组合,比先查询再插入的两步操作更高效,也能避免并发问题:
假设正式表叫official_rooms,包含room_name、building、floor、create_time字段:
INSERT INTO official_rooms (room_name, building, floor, create_time) SELECT tr.room_name, tr.building, tr.floor, NOW() FROM temp_rooms tr WHERE NOT EXISTS ( SELECT 1 FROM official_rooms ors WHERE ors.room_name = tr.room_name AND ors.building = tr.building AND ors.floor = tr.floor );
如果不想拆分字段,直接用完整文本检查也可以:
INSERT INTO official_rooms (full_room_info, create_time) SELECT tr.full_room_info, NOW() FROM temp_rooms tr WHERE NOT EXISTS ( SELECT 1 FROM official_rooms ors WHERE ors.full_room_info = tr.full_room_info );
3. 临时表清理(可选)
完成插入后,清空临时表方便下次使用:
TRUNCATE TABLE temp_rooms;
二、脚本方案(适合Python/其他语言处理)
如果你的业务逻辑需要在脚本层做更多处理(比如数据清洗、日志记录),可以用Pandas结合SQLAlchemy来实现:
import pandas as pd import sqlalchemy # 连接数据库,替换成你的连接信息 engine = sqlalchemy.create_engine('mysql+pymysql://your_username:your_password@your_host/your_db') # 读取临时表和正式表的关键数据 temp_df = pd.read_sql('SELECT room_name, building, floor FROM temp_rooms', engine) official_df = pd.read_sql('SELECT room_name, building, floor FROM official_rooms', engine) # 找出临时表中不存在于正式表的新记录 new_records = temp_df.merge(official_df, on=['room_name', 'building', 'floor'], how='left', indicator=True) new_records = new_records[new_records['_merge'] == 'left_only'].drop('_merge', axis=1) # 给新记录加创建时间 new_records['create_time'] = pd.Timestamp.now() # 插入到正式表 if not new_records.empty: new_records.to_sql('official_rooms', engine, if_exists='append', index=False) print(f"成功新增{len(new_records)}条记录") else: print("没有需要新增的记录")
这两种方案都能很好地解决你的需求,根据你的技术栈选就行~
内容的提问来源于stack exchange,提问作者OnlyDean
相关产品推荐
相关产品推荐

