在横向联接SQLAlchemy中添加计算列

时间:2018-10-11 11:53:25

标签: python postgresql sqlalchemy

我正在尝试在SQLAlchemy中编写以下PosgreSQL查询:

SELECT DISTINCT user_id
FROM
(SELECT *, (amount * usd_rate) as usd_amount
FROM transactions AS t1
LEFT JOIN   LATERAL (
                SELECT rate as usd_rate
                FROM fx_rates fx 
                WHERE (fx.ccy = t1.currency) AND (t1.created_date > fx.ts) 
                ORDER BY fx.ts DESC
                LIMIT 1 
            ) t2 On true) AS complete_table
WHERE type = 'CARD_PAYMENT' AND usd_amount > 10

到目前为止,我通过以下方式使用子查询来进行横向联接:

lateral_query = session.query(fx_rates.rate.label('usd_rate')).filter(fx_rates.ccy == transactions.currency,
                             transactions.created_date > fx_rates.ts).order_by(desc(fx_rates.ts)).limit(1).subquery('rates_lateral').lateral('rates')



task2_query = session.query(transactions).outerjoin(lateral_query,true()).filter(transactions.type == 'CARD_PAYMENT')
print(task2_query)

这将产生:

SELECT transactions.currency AS transactions_currency, transactions.amount AS transactions_amount, transactions.state AS transactions_state, transactions.created_date AS transactions_created_date, transactions.merchant_category AS transactions_merchant_category, transactions.merchant_country AS transactions_merchant_country, transactions.entry_method AS transactions_entry_method, transactions.user_id AS transactions_user_id, transactions.type AS transactions_type, transactions.source AS transactions_source, transactions.id AS transactions_id 
FROM transactions LEFT OUTER JOIN LATERAL (SELECT fx_rates.rate AS usd_rate 
FROM fx_rates 
WHERE fx_rates.ccy = transactions.currency AND transactions.created_date > fx_rates.ts ORDER BY fx_rates.ts DESC 
 LIMIT %(param_1)s) AS rates ON true 
WHERE transactions.type = %(type_1)s

哪个打印正确的横向查询,但到目前为止我还不知道如何添加计算字段(金额* usd_rate),因此我可以应用distinct和where语句。

1 个答案:

答案 0 :(得分:1)

Query中添加所需的实体,为其提供标签,然后像在SQL中一样将结果用作子查询:

task2_query = session.query(
        transactions,
        (transactions.amount * lateral_query.c.usd_rate).label('usd_amount')).\
    outerjoin(lateral_query, true()).\
    subquery()

task3_query = session.query(task2_query.c.user_id).\
    filter(task2_query.c.type == 'CARD_PAYMENT',
           task2_query.c.usd_amount > 10).\
    distinct()

另一方面,不必将其包装在子查询中,因为您也可以在内部查询的WHERE谓词中使用计算出的美元金额:

task2_query = session.query(transactions.user_id).\
    outerjoin(lateral_query, true()).\
    filter(transactions.type == 'CARD_PAYMENT',
           transactions.amount * lateral_query.c.usd_rate > 10).\
    distinct()