我有这些疑问:
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()
属性。
that问题显示无法使用我的窗口查询版本。
如何实现我的查询?
答案 0 :(得分:0)
我忘记了这个问题:)
有我的解决方案:
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'))