如何在peewee中实现无join的简单子查询



我想有一个简单的子查询。我想在几个地方重复使用。有些是连接,有些不是。

SQL代码应该是这样的

SELECT IF(x, y, z) as foo, table.*
FROM TABLE
WHERE condition

然后它被用在很多地方,通过foo连接和where。

有时简单地像这样:

SELECT * FROM
(
SELECT IF(x, y, z) as foo, table.*
FROM TABLE
WHERE condition
) WHERE (foo > 100)

有时更复杂,如分组、连接。

然而,我发现在wee中很难做到这一点。

我发现我可以这样做如果我使用join

query1 = table1.select(...).where(...)
query2 = table2.select(...).join(query1, on=(...))...

query1 = table1.select(...).where(...)
query2 = query1.select(...).join(table2, on=(...))...

也可以

然而,如果我只是从query1中选择,它不起作用。失败的确切代码:

query = tables.Payments.select(fn.IF(tables.Payments.payment_status > 0, tables.Payments.payment_amount, -tables.Payments.payment_amount).alias("x")).where(tables.Payments.payment_amount > 200)
query2 = query.select().where(query.c.x < 0)

我希望query2只是一个选择从支付x,根据之前的条件计算,是小于0,但相反,它产生虚假的SQL代码

SELECT  FROM `payments` AS `t1` WHERE ((`t1`.`payment_amount` > 200) AND (`t2`.`x` < 0))

这显然是错误的,不会执行

我该怎么做?这在peewee有可能吗?

我知道我可以写&;where()&;并在那里复制我的条件,但这是不好的做法,因为它是复制代码,如果我以后想改变那个条件怎么办?我要在10个地方重做吗?肯定有合适的方法来做这件事

PS:根据建议,我已经改变了我的代码,但它又产生了错误的SQL查询。

我的代码:

query = tables.Payments.select(fn.IF(tables.Payments.payment_status > 0, tables.Payments.payment_amount, -tables.Payments.payment_amount).alias("x")).where(tables.Payments.payment_amount > 200)
query2 = query.select_from(query.c.x).where(query.c.x < 0)

结果查询:

SELECT `t1`.`x` FROM (SELECT IF((`t2`.`payment_status` > 0), `t2`.`payment_amount`, `t2`.`payment_amount` DESC) AS `x` FROM `payments` AS `t2` WHERE (`t2`.`payment_amount` > 200)) AS `t1` WHERE (`t1`.`x` < 0)

正如你所看到的,它没有做减号操作,而是添加了DESC,这显然是不对的。

如何解决这个问题?

下面是一个使用select_from()包装子查询的示例:

db = SqliteDatabase(':memory:')
class Reg(db.Model):
key = TextField()
db.create_tables([Reg])
Reg.create(key='k1')
Reg.create(key='k2')
Reg.create(key='k3')
subq = Reg.select(Reg.key.alias('foo'), Reg)
query = subq.select_from(subq.c.foo).where(subq.c.foo.in_(['k1', 'k3']))
for row in query:
print(row.foo)
# k1
# k3

另一个例子,这基本上是select_from()在引擎盖下所做的:

query = Select([subq], [subq.c.foo]).bind(db)
for row in query:
print(row)
# {'foo': 'k1'}
# {'foo': 'k2'}
# {'foo': 'k3'}

对于您的问题的最后一次/最近一次编辑,用X * -1替换一元减号:

query = (Payments.select(fn.IF(
Payments.payment_status > 0,
Payments.payment_amount,
Payments.payment_amount * -1).alias("x")
).where(Payments.payment_amount > 200)
query2 = query.select_from(query.c.x).where(query.c.x < 0)

最新更新