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

时间:2015-10-15 09:08:28

标签: python sql sql-server 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;

这就是我的尝试:

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))

但是,parent_count_query == 0会生成一个bool,这会导致失败:

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

parent_count_query的类型为sqlalchemy.orm.query.Query

我还尝试添加.subquery(),将类型更改为sqlalchemy.sql.selectable.Alias,但在比较时仍然会给我False

当我打印生成的内部查询时,它看起来并不像我期望的那样:

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

我也尝试使用sqla.and_(parent_count_query == 0, root.MM_ParentID == 0)代替& - 然后我没有获得TypeError,而是为results获取以下SQL:

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

我做错了什么?

大图

我有一个包含root和children行的表,基本上看起来像这样:

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

我想要找到的是所有父级(MM_ParentID == 0)并且没有子级的子行(子查询会使MM_ParentID的所有子级等于当前的row_id item返回0行)。因此,在这种情况下,将返回row_id 2的项目。

2 个答案:

答案 0 :(得分:0)

您的问题是您无法在sqlalchemy中构建子查询,然后只需像在纯SQL中那样比较结果。

无论如何,如果我能正确理解你的问题,我会以不同的方式解决它;首先获取有父母的文章,

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

然后寻找这些根文章:

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)

当然还有其他方法;这是我发现的更简单,如果你的桌子非常大,可能不是最佳的。 (对不起,我已经为你的表名和列名使用了不同的拼写!)

希望它有所帮助。

答案 1 :(得分:0)

我最终简化了查询,因此它将孩子与父母联系起来,然后得到孩子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))