我试图在SQLAlchemy中复制此查询:
select date,
sum(case when country = 'USA' or country like '%merica' then dollars else 0 end),
sum(case when country != 'USA' and country not like '%merica' then dollars else 0 end)
from Spend
group date;
所以,我有以下查询对象:
q = connection.session.query(Spend.date, \
func.sum(func.case([ ( (Spend.country == 'USA') | (Spend.country.like('%merica') ), Spend.dollars ) ], else_ = 0) ), \
func.sum(func.case([ ( (Spend.country != 'USA') & (~Spend.country.like('%merica') ), Spend.dollars ) ], else_ = 0) )) \
.group_by(Spend.date)
当我运行此查询时,我收到以下异常:
sqlalchemy.exc.ProgrammingError: (ProgrammingError)
(1064, 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near
\'))) AS sum_1, sum(case(((\\\\"Spend\\\\".country != :na\' at line 1')
因此,显然在查询的呈现方面存在一些打嗝。但是,MySQL不会使用无效语法记录查询,当我在python中打印查询时,我得到它:
SELECT Spend.date AS Spend_Date, sum(case(%s)) AS sum_1, sum(case(%s)) AS sum_2
FROM Spend GROUP BY Spend.date
([(<sqlalchemy.sql.expression.BooleanClauseList object at 0xff6a7dec>, <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0xff86f1ac>)], [(<sqlalchemy.sql.expression.BooleanClauseList object at 0xff6a7fec>, <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0xff86f1ac>)])
我的问题有两个:我怎样才能看到呈现的查询是什么样的? (不幸的是,这个答案https://stackoverflow.com/a/5698357/125193没有帮助,因为它无法呈现BooleanClauseList)。另外,有没有人对我的查询可能有什么问题有任何提示?
谢谢!
更新
我能够对错误处理程序进行修补,以更好地了解正在呈现的SQL。
def wrap_handler(self, e, statement, parameters, cursor, context):
# Note: MySQLdb-specific
print(cursor._last_executed)
self.__handle_dbapi_exception(e, statement, parameters, cursor, context)
import types
connection.session.connection().__handle_dbapi_exception = connection.session.connection()._handle_dbapi_exception
connection.session.connection()._handle_dbapi_exception = types.MethodType(wrap_handler, connection.session.connection())
这是SQL:
SELECT `Spend`.date AS `Spend_date`,
sum(case((('\'\\"Spend\\".country = :name_1 OR \\"Spend\\".country LIKE :name_2\'', "'Spend.dollars'"),))) AS sum_1,
sum(case((('\'\\"Spend\\".country != :name_1 AND \\"Spend\\".country NOT LIKE :name_2\'', "'Spend.dollars'"),))) AS sum_2
FROM Spend
GROUP BY Spend.date
我仍然缺少实际参数,但很明显,SQL已经搞砸了。我将重新阅读func.case
的文档。
答案 0 :(得分:1)
似乎func
周围有一些严重的黑魔法。您可以调用func.anything_at_all
,SQLAlchemy将尝试将其转换为有效的SQL。诀窍是分别导入case
,然后直接调用它。
from sqlalchemy import case, func
# ...
func.sum(case([ ( (Spend.country == 'USA') | (Spend.country.like('%merica') ), Spend.dollars ) ], else_ = 0) )
# Notice that func.case is now just case
现在一切都按预期工作。