首页 > 解决方案 > 如何使用 sqlalchemy 核心编写 UPDATE 左连接多表查询(MySQL)?

问题描述

如何用 sqlalchemy 内核编写以下 sql?

update t1 left join t2 on t1.event_date=t2.event_date set t1.sales=coalesce(t2.sales,0);

标签: sqlalchemy

解决方案


在 Python 控制台中运行以下代码:

Python 3.8.2 (default, May  6 2020, 10:53:18) 
[Clang 11.0.3 (clang-1103.0.32.59)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlalchemy
>>> print(sqlalchemy.__version__)
1.3.19
>>> from sqlalchemy import update, func, table, column, types
>>> from sqlalchemy.dialects import mysql
>>> mysql_dialect = mysql.dialect()
>>> c1 = column("id", types.Integer)
>>> c2 = column("event_date", types.Date)
>>> c3 = column("sales", types.Integer)
>>> t1 = table("t1", c1, c2, c3)
>>> c1b = column("id", types.Integer)
>>> c2b = column("event_date", types.Date)
>>> c3b = column("sales", types.Integer)
>>> t2 = table("t2", c1b, c2b, c3b)
>>> j = t1.outerjoin(t2, t1.c.event_date == t2.c.event_date)
>>> v = {t1.c.sales: func.coalesce(t2.c.sales, 0)}
>>> s = update(j).values(v)
>>> print(s.compile(dialect=mysql_dialect))
UPDATE t1 LEFT OUTER JOIN t2 ON t1.event_date = t2.event_date SET sales=coalesce(t2.sales, 0)

你看,最终的结果非常接近完美的 SQL:只有语句t1.中缺少前缀。SET sales=...我认为这是 SQLAlchemy 1.3.19 的一个错误(或缺少功能)。所以我为此提交了一个问题:https ://github.com/sqlalchemy/sqlalchemy/issues/5617

它可能在某些情况下有效。但是对于您的情况,ERROR: Column 'sales' in field list is ambiguous当 SQL 在实际的 MySQL 服务器上运行时会引发,因为列名存在于两个表中(这就是模棱两可的意思)。

于 2020-09-30 编辑:

zzzeek (Mike Bayer) 提出了一种解决方法

>>> s = update(j).values(v).where(t1.c.id > 0)
>>> print(s.compile(dialect=mysql_dialect))
UPDATE t1 LEFT OUTER JOIN t2 ON t1.event_date = t2.event_date SET t1.sales=coalesce(t2.sales, 0) WHERE t1.id > 0

master他还在分支和分支中提交了针对此问题的修复程序rel_1_3。希望它会在 SQLAlchemy 的下一个 1.3.x 次要版本中尽快修复。


推荐阅读