Peewee 3 - Order by and Recursive common table expression (cte)
Peewee 3 - Order by and Recursive common table expression (cte)
工具:Peewee 3、SQLite、Python3
Peewee 3 递归通用 table 表达式 (cte) 的官方文档:
http://docs.peewee-orm.com/en/latest/peewee/querying.html#common-table-expressions
我将家谱存储在一个名为 Person
.
的简单 self-referencing table 中
结构(见下文):id
、name
、parent
、custom_order
备注:
- 如果此人是祖先/根项,parent
字段等于 null
,否则如果此人是 child[=,则等于 parent 记录的 id
51=]
- custom_order
是一个浮点数(分数来决定谁是用户最喜欢的人)
Objective:
我想检索整个家谱并首先按 parent
排序结果,然后按 custom_order
排序结果。
问题:
我设法得到了结果列表,但是 ORDER 是错误的。
数据库模型
class Person(Model):
name = CharField()
parent = ForeignKeyField('self', backref='children', null = True)
custom_order = FloatField()
注意:如果 parent
字段为空,则它是根项目
查询码
# Define the base case of our recursive CTE. This will be people that have a null parent foreign-key.
Base = Person.alias()
base_case = (Base
.select(Base)
.where(Base.parent.is_null())
.cte('base', recursive=True))
# Define the recursive terms.
RTerm = Person.alias()
recursive = (RTerm
.select(RTerm)
.join(base_case, on=(RTerm.parent == base_case.c.id)))
# The recursive CTE is created by taking the base case and UNION ALL with the recursive term.
cte = base_case.union_all(recursive)
# We will now query from the CTE to get the people
query = cte.select_from(cte.c.id, cte.c.name, cte.c.parent_id, cte.c.custom_order).order_by(cte.c.parent_id, cte.c.custom_order)
print(query.sql())
打印的查询语法
('WITH RECURSIVE "base" AS
(
SELECT "t1"."id", "t1"."name", "t1"."parent_id", "t1"."custom_order" FROM "person" AS "t1" WHERE ("t1"."parent_id" IS ?)
UNION ALL
SELECT "t2"."id", "t2"."name", "t2"."parent_id", "t2"."custom_order" FROM "person" AS "t2" INNER JOIN "base" ON ("t2"."parent_id" = "base"."id")
)
SELECT "base"."id", "base"."name", "base"."parent_id" FROM "base"
ORDER BY "base"."parent_id", "base"."custom_order"',
[None])
问题根源
问题中发布的代码工作正常。我通过将查询结果打印到控制台来验证它:
query = cte.select_from(cte.c.id, cte.c.name, cte.c.parent_id, cte.c.custom_order).order_by(cte.c.parent_id, cte.c.custom_order).dicts()
print(json.dumps(list(query), indent=4))
问题源于我将查询结果传递给嵌套的 python Dictionary
,然后再将它们打印到控制台,但是 Python Dictionary
无序。所以,难怪打印结果的顺序与数据库结果的顺序不同。
解决方案
如果要以固定顺序存储查询结果,请使用 Python Ordered Dictionary
:
import collections
treeDictionary = collections.OrderedDict()
工具:Peewee 3、SQLite、Python3
Peewee 3 递归通用 table 表达式 (cte) 的官方文档:
http://docs.peewee-orm.com/en/latest/peewee/querying.html#common-table-expressions
我将家谱存储在一个名为 Person
.
的简单 self-referencing table 中
结构(见下文):id
、name
、parent
、custom_order
备注:
- 如果此人是祖先/根项,parent
字段等于 null
,否则如果此人是 child[=,则等于 parent 记录的 id
51=]
- custom_order
是一个浮点数(分数来决定谁是用户最喜欢的人)
Objective:
我想检索整个家谱并首先按 parent
排序结果,然后按 custom_order
排序结果。
问题:
我设法得到了结果列表,但是 ORDER 是错误的。
数据库模型
class Person(Model):
name = CharField()
parent = ForeignKeyField('self', backref='children', null = True)
custom_order = FloatField()
注意:如果 parent
字段为空,则它是根项目
查询码
# Define the base case of our recursive CTE. This will be people that have a null parent foreign-key.
Base = Person.alias()
base_case = (Base
.select(Base)
.where(Base.parent.is_null())
.cte('base', recursive=True))
# Define the recursive terms.
RTerm = Person.alias()
recursive = (RTerm
.select(RTerm)
.join(base_case, on=(RTerm.parent == base_case.c.id)))
# The recursive CTE is created by taking the base case and UNION ALL with the recursive term.
cte = base_case.union_all(recursive)
# We will now query from the CTE to get the people
query = cte.select_from(cte.c.id, cte.c.name, cte.c.parent_id, cte.c.custom_order).order_by(cte.c.parent_id, cte.c.custom_order)
print(query.sql())
打印的查询语法
('WITH RECURSIVE "base" AS
(
SELECT "t1"."id", "t1"."name", "t1"."parent_id", "t1"."custom_order" FROM "person" AS "t1" WHERE ("t1"."parent_id" IS ?)
UNION ALL
SELECT "t2"."id", "t2"."name", "t2"."parent_id", "t2"."custom_order" FROM "person" AS "t2" INNER JOIN "base" ON ("t2"."parent_id" = "base"."id")
)
SELECT "base"."id", "base"."name", "base"."parent_id" FROM "base"
ORDER BY "base"."parent_id", "base"."custom_order"',
[None])
问题根源
问题中发布的代码工作正常。我通过将查询结果打印到控制台来验证它:
query = cte.select_from(cte.c.id, cte.c.name, cte.c.parent_id, cte.c.custom_order).order_by(cte.c.parent_id, cte.c.custom_order).dicts()
print(json.dumps(list(query), indent=4))
问题源于我将查询结果传递给嵌套的 python Dictionary
,然后再将它们打印到控制台,但是 Python Dictionary
无序。所以,难怪打印结果的顺序与数据库结果的顺序不同。
解决方案
如果要以固定顺序存储查询结果,请使用 Python Ordered Dictionary
:
import collections
treeDictionary = collections.OrderedDict()