【发布时间】:2018-04-11 21:36:46
【问题描述】:
我有一个 hybrid_property,它根据一对多关系上的一些计算返回一个字符串。
hybrid_property 表达式的原始 sql 是: 这是原始的 sql:
SELECT
CASE
WHEN s.quantity_received = 0 THEN "unreceived"
WHEN s.dif = 0.0 THEN "received"
WHEN s.dif > 0.0 THEN "partially_received"
WHEN s.dif < 0.0 THEN "over_received"
END as status
FROM (
SELECT li.quantity_received, sum(li.quantity - li.received) as 'dif'
FROM line_items as li
WHERE li.o_id = xxx
) as s
模型
class LineItem(BaseModel):
__table__ = Table('line_items', autoload=True)
order = relationship("Order", backreef="line_itms", primaryjoin="Order.id == foregin(LineItem.o_id)")
class Order(BaseModel):
__table__ = Table('orders', autoload=True)
@hybrid_property
def status(self):
qty_received, qty_ordered = 0, 0
for li in self.line_items:
if li.status != "cancelled":
qty_ordered += li.quantity
qty_received += li.quantity_received
if qty_received == 0:
status = "unreceived"
elif qty_received == qty_ordered:
status = "received"
elif qty_received < qty_ordered:
status = "partially_received"
elif qty_received > qty_ordered:
status = "over_received"
return status
@status.expression
def status(cls):
line_items_calc = select([LineItem.quantity_received,
func.sum(LineItem.quantity - LineItem.quantity_received).label('dif')]) \
.where(and_(LineItem.o_id == Order.id,
or_(LineItem.fulfillment_status != "cancelled",
LineItem.fulfillment_status == None))) \
.alias()
qq = select([
case([
(qs.c.quantity_received == 0, "unreceived"),
(qs.c.dif == 0, "received"),
(qs.c.dif > 0, "partially_received"),
(qs.c.dif < 0, "over_received")]
)]) \
.select_from(line_items_calc) \
.as_scalar()
return qq
我有 2 个订单,o1 和 o2 以及订单项:
LineItem(o_id=o1.id, quantity=1, quantity_received=1)
LineItem(o_id=o2.id, quantity=1, quantity_received=0)
LineItem(o_id=o2.id, quantity=2, quantity_received=1)
Order1 的状态应为“已收到”,而 Order2 的状态应为“partially_received”。
但是当我查询“received”时,我什么也得不到,当查询“partially_received”时,我得到 2 个结果而不是 1 个。
看起来它没有按 Order.id 过滤 LineItems,因此它使用 all 来计算状态(因为 total_qty 为 4,total received 为 2,这将给出“partially_received”)
Order.query().filter(Order.status == 'received').all() # returns []
Order.query().filter(Order.status == 'partially_received').all() # returns [Order1, Order2]
如果将 .correlate_except(LineItem) 添加到 line_items_calc 查询,我会收到以下错误:
OperationalError: (_mysql_exceptions.OperationalError) (1054, “'where 子句'中的未知列'orders.id'”)[SQL:u'SELECT count(*) AS count_1 \nFROM (SELECT * \nFROM orders \nWHERE orders.account_id = %s AND (SELECT CASE WHEN (a_3.quantity_received = %s) THEN %s WHEN (a_3.dif = %s) THEN %s WHEN (a_3.dif > %s) THEN %s WHEN (a_3.dif
【问题讨论】:
-
@IljaEverilä 是的!出于某种原因,如果我手动执行最后一个选择,它会返回正确的值,但是当用作过滤器时返回空。
-
所以我得到了部分工作,因为不是通过 cls.id 过滤得到每个 A 的每个 P,因此状态字符串错误。
-
@IljaEverilä 感谢您迄今为止的帮助。我已更新问题以提供有关模型和问题的更好信息。如果我尝试使用 correlate_except() 我得到一个错误
标签: python sqlalchemy