![](/img/trans.png)
[英]In sqlalchemy, how can I combine two queries by having a column entry identical?
[英]How can i combine two queries in sqlalchemy - raw and orm?
我有这些查询:
funds_subq = text('''select distinct on (user_id) user_id,
last_value(amount) over(PARTITION BY user_id order BY id asc RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
from transactions order by user_id, ts_spawn desc''')
g1 = aliased(Group)
u1 = aliased(User)
users = Session.query(User.id.label('user_id'),
User.name.label('user_name'),
User.funds.label('user_funds'),
Group.id.label('group_id'),
Group.parent_id.label('parent_id'),
u1.id.label('owner_id'),
u1.name.label('owner_name')). \
select_from(User). \
join(Group, Group.id == User.group_id). \
outerjoin(g1, g1.id == Group.parent_id). \
outerjoin(u1, u1.id == g1.owner_id)
那么,我如何才能将第一个加入第二个? 我尝试过这样的事情:
users = users.outerjoin(funds_subq, funds_subq.c.user_ud == User.id)
当然,它没有用,因为funds_subq没有c
属性,也没有subquery()
属性。 该问题表明无法使用我的窗口查询版本。
如何实施查询?
我忘记了这个问题:)
有我的解决方案:
from sqlalchemy.sql.expression import ColumnElement
from sqlalchemy.ext.compiler import compiles
class Extreme(ColumnElement):
def __init__(self, request_column, partition_by, order_by, last=True):
super(Extreme, self).__init__()
self.request_column = request_column
self.partition_by = partition_by
self.order_by = order_by
self.last = last
# @property
# def type(self):
# return self.func.type
def extreme_last(request_column, partition_by, order_by):
"""
function returns last_value clause like this:
last_value(transactions.remains) OVER (
PARTITION BY transaction.user_id
order BY transactions.id asc
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
it returns last value of transaction.remains for every user, that means that we can get real balance of every user
:param request_column: column, which last value we need
:param partition_by: for what entity do we need last_value, e.g. user_id
:param order_by: ordering for get last_value
:return:
"""
return Extreme(request_column, partition_by, order_by)
def extreme_first(request_column, partition_by, order_by):
"""
as same as the `extreme_last` above, but returns first value
:param request_column:
:param partition_by:
:param order_by:
:return:
"""
return Extreme(request_column, partition_by, order_by, last=False)
@compiles(Extreme)
def compile_keep(extreme, compiler, **kwargs):
return "%s(%s) OVER (PARTITION BY %s order BY %s asc RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)" % (
"last_value" if extreme.last else "first_value",
compiler.process(extreme.request_column),
compiler.process(extreme.partition_by),
compiler.process(extreme.order_by)
)
并且有一个使用示例。 查询返回每个用户最后一行的remains
字段:
Session.query(distinct(Transaction.user_id).label('user_id'),
extreme_last(Transaction.remains,
partition_by=Transaction.user_id,
order_by=Transaction.id).label('remains'))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.