如何正确排序、分组查询以返回 orm 对象的元组和自定义列?
我正在寻找一种方法来进行查询,该查询返回一个元组,首先按列排序,然后按另一个列分组(按该顺序)。只是 .sort_by().group_by()
似乎不起作用。现在我尝试了以下操作,这使得返回值出错(我只是得到了orm对象,而不是初始元组),但请自己详细阅读:
基本场景:
有一个查询用于通过外键从 test3
表链接的测试 orm 对象。 此查询还返回一个名为 linked
的列,其中包含 true
或 false
。它最初是未分组的。
my_query = session.query(test_orm_object)
... lots of stuff like joining various things ...
add_column(..condition that either puts 'true' or 'false' into the column..)
因此,原始返回值是一个元组(orm 对象,以及 true/false 列)。
现在,此查询应针对测试 orm 对象进行分组(因此 test.id
列),但在此之前,按链接列排序,因此在执行期间优先选择具有 true
的条目分组。
假设当前未排序、未分组的查询存储在 my_query 中,我实现此目的的方法是:
# Get a sorted subquery
tmpquery = my_query.order_by(desc('linked')).subquery()
# Read the column out of the sub query
my_query = session.query(tmpquery).add_columns(getattr(tmpquery.c,'linked').label('linked'))
my_query = my_query.group_by(getattr(tmpquery.c, 'id')) # Group objects
运行此查询时生成的 SQL 查询是(顺便说一句,它看起来很好 - 子查询 'anon_1
' 位于内部本身正确排序,然后获取它的 id 以及“linked
”列被提取(在 SQLAlchemy 显然想要的其他一些列中),并且结果是正确的分组):
SELECT anon_1.id AS anon_1_id, anon_1.name AS anon_1_name, anon_1.fk_test3 AS anon_1_fk_test3, anon_1.linked AS anon_1_linked, anon_1.linked AS linked
FROM (
SELECT test.id AS id, test.name AS name, test.fk_test3 AS fk_test3, CASE WHEN (anon_2.id = 87799534) THEN 'true' ELSE 'false' END AS linked
FROM test LEFT OUTER JOIN (SELECT test3.id AS id, test3.fk_testvalue AS fk_testvalue
FROM test3)
AS anon_2 ON anon_2.fk_testvalue = test.id ORDER BY linked DESC
)
AS anon_1 GROUP BY anon_1.id
我在 phpmyadmin 中测试了它,正如预期的那样,它给了我 id 列(对于 orm 对象 id),然后是 SQL_Alchemy 似乎想要的附加列,以及链接列。到目前为止,一切都很好。
现在我的预期返回值将是,因为它们来自原始的未排序、未分组的查询:
A tuple: 'test' orm object (anon_1.id column), 'true'/'false' value (linked column)
然而,新的排序/分组查询的实际返回值是(原始查询确实在应用上面的代码之前返回一个元组): 仅“测试”orm 对象
为什么会这样以及如何修复它?
如果这种方法被证明有些缺陷,请原谅。 我真正想要的是,对原始查询进行简单排序,然后进行分组而不触及返回值。正如您在上面所看到的,我尝试再次“恢复”额外的返回值,但这不起作用。如果这种方法从根本上来说是错误的,我该怎么办?
子查询使用说明:
整个子查询的要点是强制 SQLAlchemy 单独执行此查询作为第一步。
我想先对结果进行排序,然后对排序后的结果进行分组。这似乎很难一步正确地完成(当我手动尝试使用 SQL 时,我在按照我想要的一步将 order 和 group by 组合在一起时遇到了问题)。
因此,我不是简单地排序、分组,而是先排序,然后对其进行子查询以强制排序步骤实际上首先完成,然后对其进行分组。
从使用生成的 SQL 进行手动 PHPMyAdmin 测试来看,这似乎工作得很好。实际的问题是原始查询(现在被包装为您感到困惑的子查询)添加了一个列,现在通过将其包装为子查询,该列从整体结果中消失了。我尝试将其重新添加到外包装上失败了。
I am looking for a way to have a query that returns a tuple first sorted by a column, then grouped by another (in that order). Simply .sort_by().group_by()
didn't appear to work. Now I tried the following, which made the return value go wrong (I just got the orm object, not the initial tuple), but read for yourself in detail:
Base scenario:
There is a query which queries for test orm objects linked from the test3
table through foreign keys.
This query also returns a column named linked
that either contains true
or false
. It is originally ungrouped.
my_query = session.query(test_orm_object)
... lots of stuff like joining various things ...
add_column(..condition that either puts 'true' or 'false' into the column..)
So the original return value is a tuple (the orm object, and additionally the true/false column).
Now this query should be grouped for the test orm objects (so the test.id
column), but before that, sorted by the linked column so entries with true
are preferred during the grouping.
Assuming the current unsorted, ungrouped query is stored in my_query, my approach to achieve this was this:
# Get a sorted subquery
tmpquery = my_query.order_by(desc('linked')).subquery()
# Read the column out of the sub query
my_query = session.query(tmpquery).add_columns(getattr(tmpquery.c,'linked').label('linked'))
my_query = my_query.group_by(getattr(tmpquery.c, 'id')) # Group objects
The resulting SQL query when running this is (it looks fine to me btw - the subquery 'anon_1
' is inside itself properly sorted, then fetched and its id aswell as the 'linked
' column is extracted (amongst a few other columns SQLAlchemy wants to have apparently), and the result is properly grouped):
SELECT anon_1.id AS anon_1_id, anon_1.name AS anon_1_name, anon_1.fk_test3 AS anon_1_fk_test3, anon_1.linked AS anon_1_linked, anon_1.linked AS linked
FROM (
SELECT test.id AS id, test.name AS name, test.fk_test3 AS fk_test3, CASE WHEN (anon_2.id = 87799534) THEN 'true' ELSE 'false' END AS linked
FROM test LEFT OUTER JOIN (SELECT test3.id AS id, test3.fk_testvalue AS fk_testvalue
FROM test3)
AS anon_2 ON anon_2.fk_testvalue = test.id ORDER BY linked DESC
)
AS anon_1 GROUP BY anon_1.id
I tested it in phpmyadmin, where it gave me, as expected, the id column (for the orm object id), then the additional columns SQL_Alchemy seems to want there, and the linked column. So far, so good.
Now my expected return values would be, as they were from the original unsorted, ungrouped query:
A tuple: 'test' orm object (anon_1.id column), 'true'/'false' value (linked column)
The actual return value of the new sorted/grouped query is however (the original query DOES indeed return a touple before the code above is applied):
'test' orm object only
Why is that so and how can I fix it?
Excuse me if that approach turns out to be somewhat flawed.
What I actually want is, have the original query simply sorted, then grouped without touching the return values. As you can see above, my attempt was to 'restore' the additional return value again, but that didn't work. What should I do instead, if this approach is fundamentally wrong?
Explanation for the subquery use:
The point of the whole subquery is to force SQLAlchemy to execute this query separately as a first step.
I want to order the results first, and then group the ordered results. That seems to be hard to do properly in one step (when trying manually with SQL I had issues combining order and group by in one step as I wanted).
Therefore I don't simply order, group, but I order first, then subquery it to enforce that the order step is actually completed first, and then I group it.
Judging from manual PHPMyAdmin tests with the generated SQL, this seems to work fine. The actual problem is that the original query (which is now wrapped as the subquery you were confused about) had an added column, and now by wrapping it up as a subquery, that column is gone from the overall result. And my attempt to readd it to the outer wrapping failed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果能提供例子就更好了。我不知道这些列是否位于单独的表中。看看你的第一段,我会做这样的事情:
我不知道你到底想做什么,因为我需要查看你的实际模型,但它应该看起来像这样,也许有表格/对象翻转或更多过滤器。
It would be much better if you provided examples. I don't know if these columns are in separate tables or what not. Just looking at your first paragraph, I would do something like this:
I don't know exactly what you're trying to do since I need to look at your actual model, but it should look something like this with maybe the tables/objs flipped around or more filters.