我正在尝试构建一个相对复杂的查询,并希望直接操作结果的where子句,而无需克隆/子查询返回的查询。一个例子如下:
session = sessionmaker(bind=engine)()
def generate_complex_query():
return select(
columns=[location.c.id.label('id')],
from_obj=location,
whereclause=location.c.id>50
).alias('a')
query = generate_complex_query()
# based on this query, I'd like to add additional where conditions, ideally like:
# `query.where(query.c.id<100)`
# but without subquerying the original query
# this is what I found so far, which is quite verbose and it doesn't solve the subquery problem
query = select(
columns=[query.c.id],
from_obj=query,
whereclause=query.c.id<100
)
# Another option I was considering was to map the query to a class:
# class Location(object):pass
# mapper(Location, query)
# session.query(Location).filter(Location.id<100)
# which looks more elegant, but also creates a subquery
result = session.execute(query)
for r in result:
print r
这是生成的查询:
SELECT a.id
FROM (SELECT location.id AS id
FROM location
WHERE location.id > %(id_1)s) AS a
WHERE a.id < %(id_2)s
我想获得:
SELECT location.id AS id
FROM location
WHERE id > %(id_1)s and
id < %(id_2)s
有没有办法实现这个目标?这样做的原因是我认为查询(2)稍微快一点(不多),我所用的映射器示例(上面的第二个例子)弄乱了标签(id
变为anon_1_id
如果我命名别名,则为a.id
。
答案 0 :(得分:0)
你为什么不这样做:
query = generate_complex_query()
query = query.where(location.c.id < 100)
基本上你可以改进这样的任何查询。另外,我建议阅读非常棒的SQL Expression Language Tutorial并介绍您需要的所有技术。构建select
的方式只是一种方式。通常,我构建的查询更像是:select(column).where(expression).where(next_expression)
等等。 FROM
通常由SQLAlchemy从上下文中自动推断出来,即您很少需要指定它。
由于您无法访问generate_complex_query
的内部,请尝试以下操作:
query = query.where(query.c.id < 100)
这应该适合我的情况。
另一个想法:
query = query.where(text("id < 100"))
这使用SQLAlchemy的text表达式。这可能对你有用,但这是重要:如果你想引入变量,请阅读上面链接的API的描述,因为只使用绑定参数的格式字符串整数将打开你的SQL注入,这通常是SQLAlchemy的明智之举,但如果使用这些文字表达式,必须要注意。
另请注意,这是有效的,因为您将列标记为id
。如果你不这样做并且不知道列名,那么这也不会有用。