<think>嗯,我现在需要解决的问题是在Python中如何将Oracle数据库查询中BSLLOT表的结果作为参数传递给WAT_WAFER_SUMMARY表,再进行关联,最后获取两个表中的字段。让我仔细想想这个过程应该怎么处理。
首先,用户提供的SQL语句是一个LEFT JOIN,连接条件是四个字段:BSL_PRODUCT_ID、bsl_LOT_ID、bsl_WAFER_ID和WAT_PARAMETER_ID。这说明BSLLOT和WAT_WAFER_SUMMARY之间通过这四个字段进行关联。现在用户希望在Python中先查询BSLLOT的数据,然后将这些数据作为参数传递给WAT_WAFER_SUMMARY,再进行关联,最后获取两个表的字段。
我需要考虑如何分步实现这个需求。可能的方法有两种:一种是一次性在数据库中使用JOIN完成查询,另一种是分两次查询,先查BSLLOT,然后根据查到的结果去查WAT_WAFER_SUMMARY,再在Python中进行关联。
第一种方法直接在数据库里执行JOIN,效率更高,因为数据库的JOIN优化通常比在应用层处理更高效。但如果BSLLOT的数据量很大,或者需要分批处理,可能需要分步查询。但用户明确说要把BSLLOT查询出来的值作为参数传递给WAT_WAFER_SUMMARY,这可能意味着他们希望分两步操作。
那问题来了,如何将BSLLOT查询的结果中的四个字段提取出来,作为参数去查询WAT_WAFER_SUMMARY表。然后,如何将这两个结果在Python中关联起来,合并成包含两个表字段的结果集。
首先,我需要连接到Oracle数据库,使用cx_Oracle或者其他库。假设已经安装好了cx_Oracle。
第一步,查询BSLLOT表的所有数据,或者特定条件下的数据。比如:
SELECT * FROM BSLLOT;
或者可能有限制条件,但用户没有提到,所以先假设是全部数据。但要注意,如果BSLLOT的数据量很大,这样可能会影响性能,可能需要分页或者分批处理。
第二步,从BSLLOT的结果中提取四个字段的值:BSL_PRODUCT_ID、bsl_LOT_ID、bsl_WAFER_ID、WAT_PARAMETER_ID。这些值将作为参数传递给WAT_WAFER_SUMMARY的查询条件。这里需要考虑如何构建一个IN查询或者多个条件,因为每个BSLLOT行对应这四个字段的值,可能需要用OR连接多个条件。
但使用IN子句的话,如果四个字段的组合很多,可能会导致SQL语句过长,效率低下。另一种方法是使用参数化查询,分批查询,或者在Python中进行循环处理,逐行查询对应的WAT_WAFER_SUMMARY记录。
不过这样做的话,如果BSLLOT有N条记录,就需要执行N次查询,效率可能很低。因此,更好的方法可能是将BSLLOT查询出的四个字段组合成一个临时表或者使用子查询,然后在数据库中直接JOIN。不过用户要求在Python中处理,所以可能需要另一种方式。
或者,可以将BSLLOT中这四个字段的值提取出来,构造一个WHERE条件,例如:
SELECT * FROM WAT_WAFER_SUMMARY WHERE (PRODUCT_ID, LOT_ID, WAFER_ID, WAT_PARAMETER_ID) IN ( (值1, 值2, 值3, 值4), (值5, 值6, 值7, 值8), ... )
但Oracle是否支持这种多列的IN子句?我记得Oracle可能不支持这种写法,可能需要用多个OR连接的AND条件,比如:
SELECT * FROM WAT_WAFER_SUMMARY WHERE
(PRODUCT_ID = :1 AND LOT_ID = :2 AND WAFER_ID = :3 AND WAT_PARAMETER_ID = :4)
OR (PRODUCT_ID = :5 AND LOT_ID = :6 ... )
但这样的话,参数的数量会随着BSLLOT的行数增加而线性增长,可能需要动态生成SQL语句。这可能会导致SQL语句非常长,超出数据库的处理能力,或者容易引发SQL注入的问题,如果参数是动态拼接的话。不过如果使用参数化查询,应该可以避免注入问题,但参数数量可能有限制。
例如,假设BSLLOT查询结果有1000行,那么每个行对应四个参数,那么总共有1000*4=4000个参数。而Oracle数据库可能对参数数量有限制,比如每个语句最多1000个参数,这样的话,可能需要分批次处理。
这种情况下,可能更有效的方式还是直接在数据库中执行JOIN,而不是在Python中处理。但用户的需求可能需要在Python中进行处理,比如BSLLOT的数据是动态生成的,或者需要先进行某些处理,或者需要分步骤操作。
那么,假设必须分两步,首先获取BSLLOT的数据,然后根据这些数据获取对应的WAT_WAFER_SUMMARY的记录,然后在Python中进行合并。如何操作呢?
步骤可能是:
1. 查询BSLLOT表,获取所有需要的记录,保存为DataFrame或列表。
2. 提取BSLLOT中的四个字段的值,作为参数,构造一个查询条件,从WAT_WAFER_SUMMARY表中获取对应的记录。
3. 将BSLLOT和WAT_WAFER_SUMMARY的数据根据四个字段进行合并,类似于LEFT JOIN的效果。
这个过程需要注意几个问题:
- 如何高效地构造查询条件,避免多次查询数据库。
- 合并数据时的正确性,确保四个字段的匹配。
- 处理可能存在的重复记录或缺失记录的情况。
比如,在Python中,可以使用pandas库来处理数据。首先,用cx_Oracle读取BSLLOT的数据到DataFrame,然后根据这四个字段的值构造查询条件,获取WAT_WAFER_SUMMARY的数据到另一个DataFrame,然后使用merge方法进行合并,类似于SQL的LEFT JOIN。
这可能是一个更高效的方式,因为只需要两次查询,然后在内存中进行合并。这对于数据量不是特别大的情况是可行的。
具体步骤:
1. 连接数据库,读取BSLLOT表的数据:
import cx_Oracle
import pandas as pd
dsn = cx_Oracle.makedsn(host='hostname', port='port', service_name='service_name')
conn = cx_Oracle.connect(user='username', password='password', dsn=dsn)
query_bsl = "SELECT * FROM BSLLOT"
df_bsl = pd.read_sql(query_bsl, conn)
2. 提取四个字段的值,构造参数:
参数需要是四个字段的元组列表:
params = list(df_bsl[['BSL_PRODUCT_ID', 'bsl_LOT_ID', 'bsl_WAFER_ID', 'WAT_PARAMETER_ID']].to_records(index=False))
或者转换为元组的列表:
params = [tuple(x) for x in df_bsl[['BSL_PRODUCT_ID', 'bsl_LOT_ID', 'bsl_WAFER_ID', 'WAT_PARAMETER_ID']].values]
然后构造查询语句。如果参数很多,可以使用OR连接多个条件,但这种方法在参数多的时候可能效率不高,或者受到SQL语句长度的限制。另一种方法是使用临时表,将参数插入到临时表中,然后进行JOIN,但可能需要数据库的写权限,并且步骤更多。
或者,使用参数化查询,构造一个带有多个占位符的IN子句。但Oracle的SQL语法可能不支持多列的IN子句。例如,正确的写法可能是:
SELECT * FROM WAT_WAFER_SUMMARY WHERE (PRODUCT_ID, LOT_ID, WAFER_ID, WAT_PARAMETER_ID) IN (:1, :2, :3, :4)
但这样的占位符需要每个元组对应四个参数,而Oracle可能不支持这种语法。例如,在cx_Oracle中,可能需要使用tuples参数。
例如,可以这样构造:
placeholders = ', '.join([':' + str(i+1) for i in range(len(params)*4)])
# 但这样可能不正确,因为每个参数是一个四元组,需要用四个占位符表示每个元组。
正确的写法可能需要每个元组对应四个参数,例如:
SELECT * FROM WAT_WAFER_SUMMARY WHERE (PRODUCT_ID, LOT_ID, WAFER_ID, WAT_PARAMETER_ID) IN ((:1, :2, :3, :4), (:5, :6, :7, :8), ... )
然后,将参数展开为一个扁平的列表。例如,对于params中的每个四元组,将其四个元素依次添加到参数列表中。例如,参数列表应该是 [p[0], p[1], p[2], p[3], ... ],每个四元组对应四个参数。
但这样的话,占位符的数量是4*N,其中N是BSLLOT的行数。假设N很大,这会导致SQL语句非常长,可能超出数据库的限制。例如,如果N是1000,占位符数量是4000,这可能超过Oracle的最大允许参数数量(默认可能较小,比如1000)。
因此,这种方法可能不可行,特别是当BSLLOT的数据量很大时。
另一种方法是分批次查询。例如,每次处理100行,构造多个IN条件,分多次查询,然后将结果合并。
或者,使用更高效的方式,比如使用原始SQL中的JOIN,或者在Python中使用pandas的merge函数。
如果BSLLOT的数据量不大,那么在Python中进行merge可能是可行的。例如:
query_wws = "SELECT * FROM WAT_WAFER_SUMMARY"
df_wws = pd.read_sql(query_wws, conn)
然后,将两个DataFrame根据四个字段进行左连接:
merged_df = pd.merge(df_bsl, df_wws, how='left', left_on=['BSL_PRODUCT_ID', 'bsl_LOT_ID', 'bsl_WAFER_ID', 'WAT_PARAMETER_ID'], right_on=['PRODUCT_ID', 'LOT_ID', 'WAFER_ID', 'WAT_PARAMETER_ID'])
但这样会将整个WAT_WAFER_SUMMARY表加载到内存中,如果这个表很大,可能导致内存不足。此时,可能还是需要在数据库中进行JOIN操作,而不是在Python中处理。
因此,用户的问题可能的最佳实践是直接在数据库中执行JOIN,这样效率更高,代码也更简单。但用户可能因为某些原因需要在Python中分步骤处理,比如BSLLOT的数据需要先处理,或者无法直接访问两个表的同时权限等。
如果必须在Python中分步处理,可以按照以下步骤:
1. 查询BSLLOT表,获取数据。
2. 提取需要的四个字段的值。
3. 使用这些值构造参数,查询WAT_WAFER_SUMMARY表,获取对应的记录。
4. 将两个结果集根据四个字段进行合并。
在Python中,可以使用pandas的merge函数,或者使用字典来建立索引,以快速查找对应的记录。例如:
首先,读取BSLLOT数据到df_bsl。
然后,读取WAT_WAFER_SUMMARY的数据,但只读取那些在BSLLOT中存在的四个字段组合。为此,需要构造一个查询,只选择与BSLLOT中的四元组匹配的记录。
如果BSLLOT中的四元组很多,使用参数化查询可能变得复杂。这时候可以使用临时表,或者分批次查询。
不过,更高效的方式可能是在SQL中使用子查询,例如:
SELECT wws.*
FROM WAT_WAFER_SUMMARY wws
WHERE (wws.PRODUCT_ID, wws.LOT_ID, wws.WAFER_ID, wws.WAT_PARAMETER_ID) IN
(SELECT BSL_PRODUCT_ID, bsl_LOT_ID, bsl_WAFER_ID, WAT_PARAMETER_ID FROM BSLLOT)
这样可以直接在数据库中完成过滤,只获取相关的WWS记录。这可能比在Python中处理更高效。
但用户的需求似乎是要先在Python中获取BSLLOT的数据,再作为参数传递给WWS的查询,这可能是因为BSLLOT的数据是动态生成的,或者在查询BSLLOT之后需要做一些处理,然后再关联WWS。
假设必须分步在Python中处理,那么:
步骤:
1. 查询BSLLOT表,得到df_bsl。
2. 提取四个字段的组合,去重,以避免重复查询。
3. 构造参数化的SQL查询,查询WWS表中匹配这些四元组的记录。
4. 将结果保存到df_wws。
5. 合并df_bsl和df_wws,基于四个字段进行左连接。
例如:
unique_params = df_bsl[['BSL_PRODUCT_ID', 'bsl_LOT_ID', 'bsl_WAFER_ID', 'WAT_PARAMETER_ID']].drop_duplicates()
然后,构造参数化的查询。由于Oracle可能不支持多列IN,可能需要使用OR连接的多个条件:
base_query = """
SELECT *
FROM WAT_WAFER_SUMMARY
WHERE """
conditions = []
params = []
for idx, row in unique_params.iterrows():
conditions.append("(PRODUCT_ID = :{} AND LOT_ID = :{} AND WAFER_ID = :{} AND WAT_PARAMETER_ID = :{})".format(
idx*4+1, idx*4+2, idx*4+3, idx*4+4))
params.extend([row['BSL_PRODUCT_ID'], row['bsl_LOT_ID'], row['bsl_WAFER_ID'], row['WAT_PARAMETER_ID']])
query_wws = base_query + " OR ".join(conditions)
然后,执行这个查询:
df_wws = pd.read_sql(query_wws, conn, params=params)
但这种方法在unique_params行数较多时,会导致SQL语句非常长,可能超出数据库的限制,或者性能低下。例如,如果有1000行unique_params,就会生成1000个OR条件,每个条件有四个参数,总共有4000个参数,这可能超出数据库的处理能力。
这种情况下,更好的方法可能是分批次处理,比如每次处理100个四元组,多次查询,然后合并结果。
或者,使用临时表。将BSLLOT中的四元组插入到临时表中,然后使用JOIN查询。例如:
创建临时表:
cursor = conn.cursor()
cursor.execute("""
CREATE GLOBAL TEMPORARY TABLE temp_bsl (
product_id VARCHAR2(50),
lot_id VARCHAR2(50),
wafer_id VARCHAR2(50),
wat_param_id VARCHAR2(50)
) ON COMMIT PRESERVE ROWS
""")
然后将unique_params的数据插入临时表:
insert_query = "INSERT INTO temp_bsl (product_id, lot_id, wafer_id, wat_param_id) VALUES (:1, :2, :3, :4)"
data_to_insert = [tuple(x) for x in unique_params.values]
cursor.executemany(insert_query, data_to_insert)
conn.commit()
然后查询WWS表,JOIN临时表:
query_wws = """
SELECT wws.*
FROM WAT_WAFER_SUMMARY wws
INNER JOIN temp_bsl tmp
ON wws.PRODUCT_ID = tmp.product_id
AND wws.LOT_ID = tmp.lot_id
AND wws.WAFER_ID = tmp.wafer_id
AND wws.WAT_PARAMETER_ID = tmp.wat_param_id
"""
df_wws = pd.read_sql(query_wws, conn)
这种方法可能更高效,尤其是当unique_params的数量很大时。不过,需要权限创建临时表,并且需要处理临时表的清理。
但可能用户的环境不允许创建临时表,或者不希望有额外操作。
因此,可能最终的折中方法是,如果数据量不大,直接在Python中处理,使用pandas的merge函数;如果数据量大,建议直接在数据库中使用JOIN。
回到用户的问题,用户提供的原始SQL已经是一个LEFT JOIN,所以如果可能的话,直接执行这个SQL语句,将结果一次性读取到Python中,可能是最高效的方式。即:
query = """
SELECT BSLLOT.*, wws.*
FROM BSLLOT
LEFT JOIN WAT_WAFER_SUMMARY wws
ON BSLLOT.BSL_PRODUCT_ID = wws.PRODUCT_ID
AND BSLLOT.bsl_LOT_ID = wws.LOT_ID
AND BSLLOT.bsl_WAFER_ID = wws.WAFER_ID
AND BSLLOT.WAT_PARAMETER_ID = wws.WAT_PARAMETER_ID
"""
df = pd.read_sql(query, conn)
这样直接得到合并后的结果,包含BSLLOT和WWS的所有字段。这可能更简单高效,无需分步处理。
但用户的需求可能特殊,比如BSLLOT的数据需要先处理或过滤,无法直接使用JOIN,或者需要在Python中分步处理。比如,用户可能在BSLLOT查询后需要进行一些计算,或者根据某些条件过滤,再将结果用于查询WWS。
假设用户确实需要分步处理,那么正确的步骤应该是:
1. 查询BSLLOT表,得到df_bsl。
2. 提取需要的四个字段,去重得到参数列表。
3. 根据参数列表构造查询,获取WWS的数据。
4. 合并两个DataFrame。
其中,第3步的参数构造是关键,而合并则使用pandas的merge。
例如:
import cx_Oracle
import pandas as pd
# 连接数据库
dsn = cx_Oracle.makedsn('host', 'port', service_name='service_name')
conn = cx_Oracle.connect(user='user', password='password', dsn=dsn)
# 步骤1:查询BSLLOT表
query_bsl = "SELECT * FROM BSLLOT"
df_bsl = pd.read_sql(query_bsl, conn)
# 步骤2:提取四个字段并去重
unique_keys = df_bsl[['BSL_PRODUCT_ID', 'bsl_LOT_ID', 'bsl_WAFER_ID', 'WAT_PARAMETER_ID']].drop_duplicates()
# 将unique_keys转换为参数列表,每个参数是一个四元组
tuples = [tuple(x) for x in unique_keys.to_numpy()]
# 步骤3:构造查询WWS的SQL,使用OR连接多个条件
# 注意:Oracle不支持多列IN,所以需要构造多个OR条件
placeholders = []
params = []
for i, tup in enumerate(tuples):
placeholders.append(f"(:{i*4+1}, :{i*4+2}, :{i*4+3}, :{i*4+4})")
params.extend(tup)
# 如果参数过多,可能需要分批次处理,这里假设参数数量在合理范围内
if len(tuples) == 0:
df_wws = pd.DataFrame() # 如果没有参数,返回空DataFrame
else:
query_wws = """
SELECT * FROM WAT_WAFER_SUMMARY
WHERE (PRODUCT_ID, LOT_ID, WAFER_ID, WAT_PARAMETER_ID) IN ({})
""".format(', '.join(placeholders))
df_wws = pd.read_sql(query_wws, conn, params=params)
# 步骤4:合并数据
# 注意:合并时需要指定左右字段的对应关系
merged_df = pd.merge(
df_bsl,
df_wws,
how='left',
left_on=['BSL_PRODUCT_ID', 'bsl_LOT_ID', 'bsl_WAFER_ID', 'WAT_PARAMETER_ID'],
right_on=['PRODUCT_ID', 'LOT_ID', 'WAFER_ID', 'WAT_PARAMETER_ID']
)
# 关闭连接
conn.close()
# 输出结果
print(merged_df)
不过,这里需要注意的是,如果Oracle不支持多列IN子句中的参数化占位符,上述代码可能会报错。例如,Oracle可能允许使用这样的语法:
SELECT * FROM table WHERE (col1, col2) IN ((1, 'a'), (2, 'b'))
但是当使用参数化查询时,可能无法直接传递元组参数。此时,可能需要不同的处理方式。例如,在cx_Oracle中,可能需要将每个元组作为单独的绑定变量,但这可能不可行,因为每个元组需要四个绑定变量。
这时候,可能需要测试构造这样的查询是否可行。例如,构造查询字符串为:
WHERE (PRODUCT_ID, LOT_ID, WAFER_ID, WAT_PARAMETER_ID) IN ((:1, :2, :3, :4), (:5, :6, :7, :8), ... )
然后传递一个扁平的参数列表,如 [1, 'lot1', 'wafer1', 'param1', 2, 'lot2', 'wafer2', 'param2', ... ]
如果Oracle支持这样的语法,那么上述代码可以工作。否则,可能需要使用其他方法,比如动态生成多个OR条件:
WHERE (PRODUCT_ID = :1 AND LOT_ID = :2 AND WAFER_ID = :3 AND WAT_PARAMETER_ID = :4)
OR (PRODUCT_ID = :5 AND LOT_ID = :6 AND WAFER_ID = :7 AND WAT_PARAMETER_ID = :8)
OR ...
此时,参数列表将是每个四元组的元素依次排列。
例如,对于tuples列表中的每个元组 (a, b, c, d),生成条件部分,并将参数按顺序添加。
构造这样的查询可能会更可靠,但需要注意参数数量的问题。
修改步骤3的代码:
placeholders = []
params = []
for i, tup in enumerate(tuples):
placeholders.append(f"(PRODUCT_ID = :{i*4+1} AND LOT_ID = :{i*4+2} AND WAFER_ID = :{i*4+3} AND WAT_PARAMETER_ID = :{i*4+4})")
params.extend(tup)
if len(placeholders) == 0:
# 处理无参数情况
df_wws = pd.DataFrame()
else:
query_wws = "SELECT * FROM WAT_WAFER_SUMMARY WHERE " + " OR ".join(placeholders)
df_wws = pd.read_sql(query_wws, conn, params=params)
这种方法可能更可靠,因为每个条件都是明确的AND组合,用OR连接,适用于所有支持标准SQL的数据库,包括Oracle。
但参数数量可能会很大,比如如果有1000个四元组,则会有4000个参数,这可能导致数据库拒绝执行,因为超出了参数数量的限制。例如,Oracle的默认最大游标参数可能较低,可能需要调整。
此时,分批次处理可能是必要的。例如,将tuples分成每批100个,执行多次查询,合并结果。
例如:
batch_size = 100 # 根据实际情况调整
df_wws_list = []
for i in range(0, len(tuples), batch_size):
batch = tuples[i:i+batch_size]
placeholders = []
params = []
for j, tup in enumerate(batch):
placeholders.append(f"(PRODUCT_ID = :{j*4+1} AND LOT_ID = :{j*4+2} AND WAFER_ID = :{j*4+3} AND WAT_PARAMETER_ID = :{j*4+4})")
params.extend(tup)
query_wws = "SELECT * FROM WAT_WAFER_SUMMARY WHERE " + " OR ".join(placeholders)
df_batch = pd.read_sql(query_wws, conn, params=params)
df_wws_list.append(df_batch)
df_wws = pd.concat(df_wws_list, ignore_index=True)
这样,每次处理最多100个四元组,共400个参数,可能在Oracle的限制范围内。
综上所述,最终的Python代码可能如下:
1. 查询BSLLOT数据。
2. 提取唯一四元组。
3. 分批次查询WWS表。
4. 合并结果。
最后,将BSLLOT和WWS的数据进行左连接,得到最终结果。
但需要注意的是,如果WWS表中有重复的四元组,合并后的结果可能会有重复行,需要根据业务需求处理。
此外,字段名称在两个表中可能有重复,合并后的DataFrame会有后缀_x和_y,需要处理列名冲突。例如,在pd.merge中使用suffixes参数:
merged_df = pd.merge(
df_bsl,
df_wws,
how='left',
left_on=['BSL_PRODUCT_ID', 'bsl_LOT_ID', 'bsl_WAFER_ID', 'WAT_PARAMETER_ID'],
right_on=['PRODUCT_ID', 'LOT_ID', 'WAFER_ID', 'WAT_PARAMETER_ID'],
suffixes=('_BSLLOT', '_WWS')
)
这样,同名字段会加上后缀以区分。
总结,用户的问题可以通过直接在数据库中执行JOIN得到结果,或者在Python中分步处理,具体根据数据量和环境限制选择合适的方法。在Python中的分步处理需要注意参数构造和性能问题,尤其是在数据量大的情况下,可能需要分批次查询或使用临时表。</think>在Python中实现将BSLLOT的查询结果作为参数关联WAT_WAFER_SUMMARY表,可通过以下步骤实现:
---
### **步骤 1:连接数据库并查询BSLLOT数据**
使用`cx_Oracle`连接Oracle数据库,执行基础查询获取BSLLOT表数据:
```python
import cx_Oracle
import pandas as pd
# 配置数据库连接
dsn = cx_Oracle.makedsn(host='host', port='port', service_name='service_name')
conn = cx_Oracle.connect(user='user', password='password', dsn=dsn)
# 查询BSLLOT表所有数据
query_bsl = "SELECT * FROM BSLLOT"
df_bsl = pd.read_sql(query_bsl, conn)
```
---
### **步骤 2:提取关联字段并去重**
从BSLLOT数据中提取关联所需的四个字段,并去重以避免重复查询:
```python
# 提取唯一键组合
unique_keys = df_bsl[['BSL_PRODUCT_ID', 'bsl_LOT_ID', 'bsl_WAFER_ID', 'WAT_PARAMETER_ID']].drop_duplicates()
tuples = [tuple(x) for x in unique_keys.to_numpy()]
```
---
### **步骤 3:分批次查询WAT_WAFER_SUMMARY**
根据提取的键值分批构造查询条件,避免SQL参数超限:
```python
batch_size = 100 # 按实际情况调整批次大小
df_wws_list = []
for i in range(0, len(tuples), batch_size):
batch = tuples[i:i+batch_size]
conditions, params = [], []
for idx, tup in enumerate(batch):
n = idx * 4
conditions.append(f"(PRODUCT_ID = :{n+1} AND LOT_ID = :{n+2} AND WAFER_ID = :{n+3} AND WAT_PARAMETER_ID = :{n+4})")
params.extend(tup)
query = f"SELECT * FROM WAT_WAFER_SUMMARY WHERE {' OR '.join(conditions)}"
df_batch = pd.read_sql(query, conn, params=params)
df_wws_list.append(df_batch)
df_wws = pd.concat(df_wws_list, ignore_index=True)
```
---
### **步骤 4:合并两个数据集**
使用`pd.merge`实现类似SQL的LEFT JOIN操作:
```python
merged_df = pd.merge(
df_bsl,
df_wws,
how='left',
left_on=['BSL_PRODUCT_ID', 'bsl_LOT_ID', 'bsl_WAFER_ID', 'WAT_PARAMETER_ID'],
right_on=['PRODUCT_ID', 'LOT_ID', 'WAFER_ID', 'WAT_PARAMETER_ID'],
suffixes=('_BSLLOT', '_WWS') # 处理字段重名
)
```
---
### **步骤 5:关闭连接并输出结果**
```python
conn.close()
print(merged_df) # 或导出到文件/进一步处理
```
---
### **关键说明**
1. **性能优化**:
- 若数据量较大,建议直接在数据库内使用原始`LEFT JOIN`一次性查询(更高效):
```python
query = """
SELECT BSLLOT.*, wws.*
FROM BSLLOT
LEFT JOIN WAT_WAFER_SUMMARY wws
ON BSLLOT.BSL_PRODUCT_ID = wws.PRODUCT_ID
AND BSLLOT.bsl_LOT_ID = wws.LOT_ID
AND BSLLOT.bsl_WAFER_ID = wws.WAFER_ID
AND BSLLOT.WAT_PARAMETER_ID = wws.WAT_PARAMETER_ID
"""
df = pd.read_sql(query, conn)
```
- 分批次查询适合无法直接使用JOIN或需预处理数据的场景。
2. **字段处理**:
- 合并后同名字段会自动添加后缀(如`_BSLLOT`和`_WWS`),需根据实际需求调整列名或选择保留字段。
---
通过以上步骤,可实现BSLLOT与WAT_WAFER_SUMMARY的关联查询,并获取两表的全部字段。