Peewee - 使用自定义 SQL 作为子查询

问题描述 投票:0回答:1

我在使用 Peewee 和 MySQL 时遇到了问题。基本上我想过滤用户的日志并将其分类到过去 8 周(例如第 0 周到第 7 周)。 结果应该如下所示:

{ 'userid': 1, 'week':1, 'bin': ?},
...
{ 'userid': 1, 'week':7, 'bin': ?},
{ 'userid': 2, 'week':0, 'bin': ?},
...
etc.

但是,我想确保即使用户在特定一周的日志中没有条目,它仍然显示为 'bin': 0。我会使用 OUTER JOIN,但我没有相应的“week”表来外部连接与。 在 SQL 中,我会执行以下操作:

WITH  weeks (week) AS (
VALUES ROW(0),ROW(1),ROW(2),ROW(3),ROW(4),ROW(5),ROW(6),ROW(7)
)'

然后在连接中使用“周”。但是我不知道如何在 peewee 中做到这一点。如果我创建一个“RawQuery”,我无法像使用常规查询一样使用它进行连接(它没有 .c 来访问字段或 .select())。

我最终在没有太多记录的表上使用了这样的脏修复:

max_weeks = 8
weeks = (
    MyTable.select(
        (fn.MOD(MyTable.id,max_weeks)).alias("week")
    ).distinct()
)

但我更愿意以正确的方式去做。

我必须在这里指定,我的要求是我只对数据库进行一个查询(由多个子查询组成),并且周数(在本例中为8)是可变的。另外,我对数据库具有只读权限。

mysql python-3.x peewee
1个回答
0
投票

我没有方便的 MySQL,因为我使用 MariaDB,它使用稍微不同的语法,但希望这样的东西应该可以工作:

from peewee import *
from peewee import NodeList, CommaNodeList, CTE

db = MySQLDatabase('peewee_test')

class Reg(db.Model):
    value = IntegerField()

db.create_tables([Reg])
Reg.create(value=1)

weeks = CommaNodeList([fn.ROW(i) for i in range(8)])

cte = CTE('weeks', NodeList([SQL('VALUES'), weeks]), columns=['week'])

# Just a simple cartesian product of Reg x Weeks - in your example
# you would be performing a join instead.
query = Reg.select(Reg.value, cte.c.week).from_(Reg, cte).with_cte(cte)
print(query.sql())
for row in query:
    print(row.value, row.week)

生成的SQL:

WITH `weeks` (`week`) AS (
    VALUES ROW(0), ROW(1), ROW(2), ROW(3),
           ROW(4), ROW(5), ROW(6), ROW(7)) 
SELECT `t1`.`value`, `weeks`.`week` 
FROM `reg` AS `t1`, `weeks`
© www.soinside.com 2019 - 2024. All rights reserved.