如何在sqlalchemy中定义cte/query/join-hybrid_属性,而不必为模型中的每一行重复? 模型 测试1-使用混合_属性-意外结果
运行上面的代码会导致为每个“id”重复所有“full_desc”的列表,如下所示:如何在sqlalchemy中定义cte/query/join-hybrid_属性,而不必为模型中的每一行重复? 模型 测试1-使用混合_属性-意外结果,sqlalchemy,Sqlalchemy,运行上面的代码会导致为每个“id”重复所有“full_desc”的列表,如下所示: (1, 'Category6 - Brand1 - Product1') (2, 'Category6 - Brand1 - Product1') (3, 'Category6 - Brand1 - Product1') (4, 'Category6 - Brand1 - Product1') (5, 'Category6 - Brand1 - Product1') (6, 'Category6 - Brand1
(1, 'Category6 - Brand1 - Product1')
(2, 'Category6 - Brand1 - Product1')
(3, 'Category6 - Brand1 - Product1')
(4, 'Category6 - Brand1 - Product1')
(5, 'Category6 - Brand1 - Product1')
(6, 'Category6 - Brand1 - Product1')
(7, 'Category6 - Brand1 - Product1')
(8, 'Category6 - Brand1 - Product1')
(9, 'Category6 - Brand1 - Product1')
(1, 'Category5 - Brand2 - Product2')
(2, 'Category5 - Brand2 - Product2')
(3, 'Category5 - Brand2 - Product2')
(4, 'Category5 - Brand2 - Product2')
... 81 rows in total
(1, 'Category6 - Brand1 - Product1')
(2, 'Category5 - Brand2 - Product2')
(3, 'Category7 - Brand4 - Product3')
(4, 'Category7 - Brand3 - Product4')
(5, 'Category5 - Brand1 - Product5')
(6, 'Category7 - Brand5 - Product6')
(7, 'Category3 - Brand2 - Product7')
(8, 'Category1 - Brand3 - Product8')
(9, 'Category4 - Brand3 - Product9')
外部模型定义的CTE
试验2-使用上述CTE定义(模型外)-预期结果-非预期方法
运行上面的代码会为每个id生成一个右描述列表,没有重复(只有9行),如下所示:
(1, 'Category6 - Brand1 - Product1')
(2, 'Category6 - Brand1 - Product1')
(3, 'Category6 - Brand1 - Product1')
(4, 'Category6 - Brand1 - Product1')
(5, 'Category6 - Brand1 - Product1')
(6, 'Category6 - Brand1 - Product1')
(7, 'Category6 - Brand1 - Product1')
(8, 'Category6 - Brand1 - Product1')
(9, 'Category6 - Brand1 - Product1')
(1, 'Category5 - Brand2 - Product2')
(2, 'Category5 - Brand2 - Product2')
(3, 'Category5 - Brand2 - Product2')
(4, 'Category5 - Brand2 - Product2')
... 81 rows in total
(1, 'Category6 - Brand1 - Product1')
(2, 'Category5 - Brand2 - Product2')
(3, 'Category7 - Brand4 - Product3')
(4, 'Category7 - Brand3 - Product4')
(5, 'Category5 - Brand1 - Product5')
(6, 'Category7 - Brand5 - Product6')
(7, 'Category3 - Brand2 - Product7')
(8, 'Category1 - Brand3 - Product8')
(9, 'Category4 - Brand3 - Product9')
问题:
我应该对@hybrid_属性和/或@hybridproperty.extension进行哪些更改,以获得测试2中所需的结果,但使用测试1中的方法?还是有更好的方法来实现这一点
环境
我不确定您是否应该使用
cte
。而@hybrid_属性的非表达式部分不应使用任何查询
请参阅下面的代码,这些代码应该可以工作(使用sqlalchemy 1.4版):
及有关查询:
# in-memory (not using expressions, but potentially loading categories and brands from the database)
result_1 = session.query(Product).all()
for product in result_1:
print(product.id, product.full_description)
# using .expression - get 'full_description' in one query.
result_2 = session.query(Product.id, Product.full_description).all()
for product_id, fulldesc in result_2:
print(product_id, fulldesc)
,其中后者将生成以下SQL
语句:
SELECT product.id,
(SELECT concat(category.description, %(concat_2)s, brand.description, %(concat_3)s, product.description) AS concat_1
FROM category,
brand
WHERE category.id = product.category_id
AND brand.id = product.brand_id) AS full_desc_subquery
FROM product
非常感谢@van!。但是,我似乎无法在当前环境中使用结果_2(使用.expression)。我忘了在我的问题上提到我正在使用的软件包。我使用的是sqlalchemy 1.3.20和sqlalchemy_utils 0.36.7,也是postgresql 13。我曾尝试将sqlalchemy升级到1.4.2,但它与sqlalchemy_utils冲突,后者只能升级到0.36.8。我在sqlalchemy 1.3.20中遇到的错误可以在这里找到。我尝试将语句更改为:@full_description.expression def full_description(cls):subq=(session.query(func.concat(Category.description)”-“,Brand.description,“-”,cls.description,).filter(Category.id==cls.Category\u id)。filter(Brand.id==cls.Brand\u id)。as\u scalar().label(“full\u desc\u subquery”))返回子查询以使其工作,但是这是正确的方法吗?是因为sqlalchemy 1.3.2和1.4.2之间的变化吗?我对编程非常陌生,掌握sqlalchemy的文档已经很有挑战性,更不用说跟上版本之间的变化了。我认为1.3和1.4版本之间没有什么不同。一些在1.3中被弃用的构造现在在1.4中不起作用。我用1.4进行了测试。
SQLAlchemy==1.3.20
SQLAlchemy-Utils==0.36.7
PostgreSQL 13
@hybrid_property
def full_description(self):
return self.category.description + " - " + self.brand.description + " - " + self.description
@full_description.expression
def full_description(cls):
subq = (
select(
func.concat(
Category.description,
" - ",
Brand.description,
" - ",
cls.description,
)
)
.where(Category.id == cls.category_id).where(Brand.id == cls.brand_id)
.scalar_subquery()
.label("full_desc_subquery")
)
return subq
# in-memory (not using expressions, but potentially loading categories and brands from the database)
result_1 = session.query(Product).all()
for product in result_1:
print(product.id, product.full_description)
# using .expression - get 'full_description' in one query.
result_2 = session.query(Product.id, Product.full_description).all()
for product_id, fulldesc in result_2:
print(product_id, fulldesc)
SELECT product.id,
(SELECT concat(category.description, %(concat_2)s, brand.description, %(concat_3)s, product.description) AS concat_1
FROM category,
brand
WHERE category.id = product.category_id
AND brand.id = product.brand_id) AS full_desc_subquery
FROM product