如何使用SQLAlchemy的表达语言编写条件子句?
我写了一个比较复杂的查询,用来从两个表中获取和连接一堆数据。
SELECT
/* Common attributes */
carrier.name,
carrier.notes,
carrier.turnaround,
/* Either per-reseller price, generic reseller price or default price */
IFNULL(
rsu.price,
IF(
(
carrier.reseller_price != IS NOT NULL AND
carrier.reseller_price != 0
),
carrier.reseller_price,
carrier.price
)
) AS price,
IFNULL(
rsu.price_barred,
IF(
(
carrier.reseller_price_barred IS NOT NULL AND
carrier.reseller_price_barred != 0
),
carrier.reseller_price_barred,
carrier.price_barred
)
) AS price_barred
FROM
`core_carrier` AS carrier
LEFT OUTER JOIN
`core_resellerunlock` AS rsu ON (
rsu.carrier_id = carrier.id AND
rsu.reseller_id = 1
)
有人能建议我怎么用SQLAlchemy的查询构建器来重写这个吗? 我不太确定用那些SELECT ... IF
语句是否可行。
补充:我不想用ORM(对象关系映射)来做这个,听说用SQLAlchemy的ORM纯粹执行这个是不可能的。我只是想找一种相对可移植的方法,使用SQLAlchemy的核心功能来实现。
1 个回答
2
你可以在查询中使用`case`函数来添加条件。这虽然不会生成你所展示的确切SQL语句,但可以产生功能上等效的结果。
下面是一个简单的例子,其中的carrier
和rsu
变量代表Table
对象,而case
则是指前面提到的函数:
join = carrier.join(rsu, (rsu.c.carrier_id == carrier.c.id) & (rsu.c.reseller_id == 1))
query = join.select([
carrier.c.name,
carrier.c.notes,
carrier.c.turnaround,
case([
(
rsu.c.price_barred == None,
case([
(
(carrier.c.reseller_price != None) & (carrier.c.reseller_price != 0),
carrier.c.reseller_price
)
],
else_=carrier.c.price
)
]
])
你可能会觉得创建一些辅助函数来表示更高级的IFNULL
和IF
函数会让你的查询更易读。例如:
def if_(expr, then, else_):
return case([
(expr, then)
], else_=else_)