简体   繁体   English

SQLAlchemy:在子查询中使用外部查询中的列

[英]SQLAlchemy: Use column from outer query in subquery

My issue 我的问题

I have this (MSSQL) query which I'd like to convert to SQLAlchemy: 我有这个(MSSQL)查询,我想将其转换为SQLAlchemy:

SELECT * FROM Artikel AS root WHERE (SELECT COUNT(*) FROM Artikel WHERE Artikel.MM_ParentID = root.ROW_ID) = 0 AND MM_ParentID = 0;

This is what I tried: 这是我尝试的:

root = sqlalchemy.orm.aliased(GSDArtikel, name='root')
parent_count_query = gsd_session.query(sqla.func.count()).select_from(GSDArtikel).filter(GSDArtikel.MM_ParentID == root.row_id)
results = gsd_session.query(root).filter((parent_count_query == 0) & (root.MM_ParentID == 0))

However, parent_count_query == 0 generates a bool, which makes this fail: 但是, parent_count_query == 0生成布尔值,这将导致失败:

TypeError: unsupported operand type(s) for &: 'bool' and 'BinaryExpression'

parent_count_query has the type sqlalchemy.orm.query.Query . parent_count_query有型sqlalchemy.orm.query.Query

I also tried adding .subquery() which changes the type to sqlalchemy.sql.selectable.Alias , but still gives me False when comparing it. 我也尝试添加.subquery()这类型更改为sqlalchemy.sql.selectable.Alias ,但还是给了我False的比较时。

When I print the generated inner query, it doesn't quite look like I'd expect it to: 当我打印生成的内部查询时,它看起来不太像我期望的那样:

SELECT count(*) AS count_1 
FROM [Artikel], [Artikel] AS root 
WHERE [Artikel].[MM_ParentID] = root.row_id

I also tried using sqla.and_(parent_count_query == 0, root.MM_ParentID == 0) instead of & - then I don't get a TypeError , but instead get the following SQL for results : 我也尝试使用sqla.and_(parent_count_query == 0, root.MM_ParentID == 0)代替& -然后我没有得到TypeError ,而是得到以下SQL以获得results

SELECT ...
FROM [Artikel] AS root 
WHERE 0 = 1

What am I doing wrong? 我究竟做错了什么?

The big picture 大图景

I have a table with root and children rows, which basically looks like this: 我有一个带有根行和子行的表,基本上是这样的:

| row_id | MM_ParentID |
------------------------
| 1      | 0           |
| 2      | 0           |
| 3      | 0           |
| 4      | 1           |
| 5      | 1           |
| 6      | 3           |

What I'm trying to find is all rows which are parents ( MM_ParentID == 0 ) and have no children (subquery which gets all children with MM_ParentID equal to the row_id of the current item returns 0 rows). 我想找到的是所有属于父级( MM_ParentID == 0 )并且没有子级的行(子查询将获得所有MM_ParentID等于当前项的row_id的子级的子查询返回0行)。 So in this case, the item with row_id 2 would be returned. 因此,在这种情况下,将返回具有row_id 2的项目。

Your problem is that you cannot build a subquery in sqlalchemy and then just compare the result as you would do in pure SQL . 您的问题是您无法在sqlalchemy构建子查询,然后只能像在纯SQL那样比较结果。

Anyway, if I've understood correctly your problem, I would tackle it in a different way; 无论如何,如果我正确理解了您的问题,我会以其他方式解决它; first fetching the Articles that do have a parent, 首先获取确实有父母的文章,

In [39]:
from sqlalchemy.orm import aliased
root = aliased(Article, name='root')
subq = session.query(Article.id).select_from(Article).filter(Article.parent_id == root.id)
print(subq)

SELECT article.id AS article_id 
FROM article, article AS root 
WHERE article.parent_id = root.id

And then looking for the root articles like these: 然后寻找像这样的基础文章:

In [40]:
from sqlalchemy import tuple_
results = session.query(Article).filter(~Article.id.in_(subq))
print(results)

SELECT article.id AS article_id, article.parent_id AS article_parent_id 
FROM article 
WHERE article.id NOT IN (SELECT article.id AS article_id 
FROM article AS root 
WHERE article.parent_id = root.id)

For sure there are other ways; 当然,还有其他方法。 this is the simpler I've figured out, probably not optimal if your table is very big. 这是我想出的简单方法,如果您的桌子很大,可能不是最佳选择。 (And sorry that I've used different spelling for your table and column names!) (很抱歉,我为您的表名和列名使用了不同的拼写!)

Hope it helps. 希望能帮助到你。

I ended up simplifying the query so it joins the children to the parents and then gets the ones where the child IS NULL : 我最终简化了查询,以便将孩子与父母联系起来,然后得到孩子为IS NULL的孩子:

stray_parents = (gsd_session.query(item)
                 .outerjoin(child, item.row_id == child.MM_ParentID)
                 .filter(item.MM_ParentID == 0, child.row_id == None))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM