[英]Subquery in ORDER BY SQLAlchemy
我正在尝试将SQL查询转换为SQLAlchemy查询语言。 为了稍微了解查询的含义,我提供了表安全性和表评估 。 证券表描述了我在市场上关注的不同证券(股票):
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
我要做的是在一个准确的日期将按 数量分类的第十佳证券。 问题在于,有时没有针对该特定日期(例如,周末)的数据,因此我想获取最后一个交易量值(过去的最近值)。
我已经在纯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()
)
但是:
我最终找到了解决方案:
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
效率更高,不需要重复。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.