我有两个对象列表:listA<modelA>(), listB<modelB>()
基于以下模型。
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
Base = declarative_base()
class modelA(Base):
__tablename__ = "TableA"
rowID = Column(Integer, primary_key=True)
applicationNo = Column(String)
accountNum = Column(String)
sanitizedAccountNum = Column(String)
class modelB(Base):
__tablename__ = "TableB"
rowID = Column(Integer, primary_key=True)
applicationNo = Column(String)
accountNum = Column(String)
sanitizedAccountNum = Column(String)
# create SQLAlchemy engine/connection
engine = create_engine("mysql+mysqlconnector://root:usbw@localhost:3307/testDB", echo=False)
dbSession = sessionmaker(bind=engine)
session = dbSession()
# query to pull data from DB
listA = session.query(modelA).limit(100).all()
listB = session.query(modelB).limit(100).all()
这些列表是使用SqlAlchemy填充的。每个表都包含将近一百万条记录,因此我想一次对一部分记录进行查询。
从数据库中获取数据后,我试图对以上两个列表执行SQL样式的左联接,例如下面的SQL查询:
SELECT a.applicationNo, a.sanitizedAccountNum
FROM listA a
LEFT JOIN listB b on b.applicationNo=a.applicationNo and b.sanitizedAccountNum=a.sanitizedAccountNum
WHERE b.applicationNo IS NULL;
我尝试使用Pandas的DataFrame,但无法获得正确的结果。
熊猫:
dfA = pd.DataFrame(listA)
dfB = pd.DataFrame(listB)
resultPD = pd.merge(dfA, dfB, how="left"), on=["applicationNo","sanitizedAccountNum"])
这里的“ on”子句不起作用,给我“ KeyError:'applicationNo'”。如何在上述查询中为我的模型设置“ join on”列?
跟踪:
Traceback (most recent call last):
File "dbna.py", line 58, in <module>
resultPD = pd.merge(dfA, dfB, indicator="i", how="left", on=["applicationNo","sanitizedAccountNum"])
File "C:\Users\1833\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pandas\core\reshape\merge.py", line 61, in merge validate=validate)
File "C:\Users\1833\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pandas\core\reshape\merge.py", line 551, in __init__ self.join_names) = self._get_merge_keys()
File "C:\Users\1833\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pandas\core\reshape\merge.py", line 857, in _get_merge_keys rk, stacklevel=stacklevel))
File "C:\Users\1833\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pandas\core\generic.py", line 1382, in _get_label_or_level_values raise KeyError(key)
KeyError: 'applicationNo'
还有,这是最好的方法,以“左联接” listA和listB并仅基于提到的两个特定列从listA中获取不在listB中的那些记录吗?
编辑(样本数据): TableA Sample
更新:
正如@Philip在下面的评论中建议的那样,诀窍是直接将DB结果绑定到Pandas DataFrame,而不是绑定到类(模型)的列表,然后从该列表创建DataFrame。他在评论中提供的link可以解决问题。
答案 0 :(得分:1)
一个建议可能是您在MySql中创建视图或将其作为查询,然后以记录限制或通过在熊猫中指定块大小来使用该视图。
在数据库中创建VIEW:
CREATE VIEW AB_joined AS
SELECT a.applicationNo
,a.sanitizedAccountNum
FROM listA a
LEFT JOIN listB b ON b.applicationNo = a.applicationNo
AND b.sanitizedAccountNum = a.sanitizedAccountNum
WHERE b.applicationNo IS NULL
并在熊猫中使用query1:
query1 = "SELECT * FROM AB_joined"
或直接在熊猫中使用query2:
query2 = """
SELECT a.applicationNo
,a.sanitizedAccountNum
FROM listA a
LEFT JOIN listB b ON b.applicationNo = a.applicationNo
AND b.sanitizedAccountNum = a.sanitizedAccountNum
WHERE b.applicationNo IS NULL"""
然后使用熊猫读取chunksize,您可以将不同的chunksize合并在一起吗?
result = pd.read_sql_query(query, engine, chunksize=100000)
您可以找到有关pandas.read_sql_query here
的更多信息另一个建议是直接使用sqlalchemy创建视图并执行上面的操作。在我看来,选择取决于项目的目的。您可能会发现create views in sqlalchemy here
的灵感您的第一个问题。我认为查询应如下所示:
resultPD = dfA.merge(dfB, left_on="applicationNo", right_on="sanitizedLoanAccount", how="left")
您的第二个问题。左联接是仅从listA中获取不在listB中的记录的方法。您还利用了where子句,该子句添加了应选择行的附加规则。
更新我
我刚刚意识到您的数据存储为字符串。将数据连接到字符串值不是一个好习惯。如果可能的话,我建议将存储为字符串的数字转换为整数。这样可以避免很多问题。
UPDATE II-添加的数据
我已经尝试过使用屏幕截图中的数据。只是每个使用两行。
dfA = pd.DataFrame({
'RowID' : [1,2],
'ApplicationNo': ['L0008065026','L000969215'],
'AccountNum': ['34204731277', '006737107100039'],
'SanatizedAccountNum': ['34204731277', '6737107100039']
})
dfB = pd.DataFrame({
'RowID' : [1,2],
'ApplicationNo': ['L43907','L52006'],
'AccountNum': ['3265470064', '073176310000477'],
'SanatizedAccountNum': ['3265470064', '73176310000477']
})
resultPD = dfA.merge(dfB, left_on="ApplicationNo", right_on="SanatizedAccountNum", how="left")
有了上面的内容,我就可以毫无问题地获得resultPD。