【问题标题】:Subquery in ORDER BY SQLAlchemyORDER BY SQLAlchemy 中的子查询
【发布时间】:2016-01-21 14:27:26
【问题描述】:

我正在尝试将 SQL 查询转换为 SQLAlchemy 查询语言。 为了稍微理解查询的意义,我有一个表security和一个表valuation证券表描述了我在市场上关注的不同证券(股票):

 id   |           bbg_ticker
------+-------------------------
    1 | 3993 HK Equity
    2 | A2A IM Equity
    3 | AA UN Equity
    4 | AA/ LN Equity
    5 | AAL LN Equity
    6 | AALB NA Equity
    7 | ABBN VX Equity

估值表描述了一种证券一天的价值:

security_id |    date    |  px_close   |   volume
------------+------------+-------------+-------------
          1 | 2015-05-18 |       6.754 |     9890000
          1 | 2015-05-19 |       6.802 |    11660773
          1 | 2015-05-20 |       6.802 |    12674694
          1 | 2015-05-21 |       6.735 |     5533000
          1 | 2015-05-22 |        6.85 |    10096288
          2 | 2015-05-18 |      1.0558 |    32198683
          2 | 2015-05-19 |      1.0577 |    17630748
          2 | 2015-05-20 |      1.0606 |    11990913
          2 | 2015-05-21 |      1.0722 |    24492170
          2 | 2015-05-22 |      1.0887 |    28795865
          3 | 2015-05-18 |     13.3587 |     3107029
          3 | 2015-05-19 |     13.0397 |     6276252
          3 | 2015-05-20 |     13.0297 |     3746343
          3 | 2015-05-21 |     12.9599 |     4023997
          3 | 2015-05-22 |     12.9001 |     3438908
          4 | 2015-05-18 |     403.949 |     2059825
          4 | 2015-05-19 |     404.937 |     1153599
          4 | 2015-05-20 |     405.035 |      769304
          4 | 2015-05-21 |     403.455 |      586507
          4 | 2015-05-22 |     399.998 |      878268
          5 | 2015-05-18 |    1049.328 |     4957938

我想做的是在一个精确的日期获得按交易量分类的第 10 佳证券。问题是有时这个特定日期(例如周末)没有数据,所以我想取最后一个音量值(过去最近的)。

我在纯 SQL 中找到了解决方案(这里是 2015 年 5 月 23 日的示例):

SELECT s.bbg_ticker
FROM security s
INNER JOIN valuation v1
    ON v1.security_id = s.id
    AND v1.volume IS NOT NULL
    AND v1.px_close iS NOT NULL
    AND v1.date > '2015-05-16'     # because I don't want too old values..
    AND v1.date <= '2015-05-23'
GROUP BY s.id
ORDER BY (SELECT v.volume
    FROM valuation v
    WHERE v.security_id = s.id
        AND v.volume IS NOT NULL
        AND v.px_close IS NOT NULL
        AND v.date > '2015-05-16'  # same
        AND v.date <= '2015-05-23'
    ORDER BY v.date DESC LIMIT 1
) DESC
LIMIT 10

我想做同样的事情,但使用 SQLAlchemy 查询语言。由于我的 SQL 查询中有很多重复,我很确定我可以使用 SQLAlchemy 做一些更智能的事情而无需重复。

我无法使用 SQLAlchemy 在“ORDER BY”中执行子查询。

有人有想法吗?

谢谢你, 埃德

编辑:

我的第一个想法是做类似的事情:

 Security.query.join(Valuation)\
      .filter(
          Valuation.volume != None,
          Valuation.px_close != None,
          Valuation.date <= date(2015, 05, 23),
          Valuation.date > date(2015, 05, 16)
      ).order_by(
          db.session.query(Valuation.volume).filter(
              Valuation.volume != None,
              Valuation.px_close != None,
              Valuation.date <= date(2015, 05, 23),
              Valuation.date > date(2015, 05, 16)
          ).desc()
      )

但是:

  • 我有一个关于 desc() 的错误:“AttributeError: 'BaseQuery' 对象没有属性 'desc'”
  • 我在子查询中没有链接“WHERE v.security_id = s.id”,因为我无权访问子查询中的“安全”

【问题讨论】:

    标签: python sql sqlalchemy subquery


    【解决方案1】:

    我终于找到了解决办法:

    Security.query.join(Valuation)\
            .filter(tuple_(Valuation.security_id, Valuation.date).in_(
                db.session.query(Valuation.stock_id, func.max(Valuation.date))\
                .filter(Valuation.volume != None,
                        Valuation.px_close != None,
                        Valuation.date > date(2015, 05, 16),
                        Valuation.date <= date(2015, 05, 23))
                .group_by(Valuation.security_id)))
                .order_by(Valuation.volume.desc())
                .limit(10)
                .all()
    

    产生:

    SELECT security.*
    FROM security
        JOIN valuation ON security.id = valuation.security_id
        WHERE (valuation.security_id, valuation.date) IN (
            SELECT valuation.security_id, max(valuation.date)
            FROM valuation
            WHERE valuation.volume IS NOT NULL
                AND valuation.px_close IS NOT NULL
                AND valuation.date > "2015-05-16"
                AND valuation.date <= "2015-05-23"
                GROUP BY valuation.security_id
        )
    ORDER BY valuation.volume DESC
    LIMIT 10
    

    哪个效率更高,不需要重复。

    【讨论】:

      猜你喜欢
      • 2014-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多