ORDER BY SQLAlchemy 中的子查询
Subquery in ORDER BY SQLAlchemy
我正在尝试将 SQL 查询转换为 SQLAlchemy 查询语言。
为了稍微理解查询的含义,我有一个 table security 和一个 table valuation。
证券 table 描述了我在市场上关注的不同证券(股票):
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
估价table描述了一个证券和一天[=51]的价值=]:
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' object has no attribute 'desc'"
- 我没有子查询中的link "WHERE v.security_id = s.id",因为我无法访问子查询
中的"security"
我最终找到了解决方案:
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
哪个效率更高,不需要重复。
我正在尝试将 SQL 查询转换为 SQLAlchemy 查询语言。 为了稍微理解查询的含义,我有一个 table security 和一个 table valuation。 证券 table 描述了我在市场上关注的不同证券(股票):
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
估价table描述了一个证券和一天[=51]的价值=]:
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' object has no attribute 'desc'"
- 我没有子查询中的link "WHERE v.security_id = s.id",因为我无法访问子查询 中的"security"
我最终找到了解决方案:
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
哪个效率更高,不需要重复。