Peewee group_concat/case 问题
Peewee group_concat/case issue
我正在尝试使用 peewee 来获取和格式化来自使用 GROUP_CONCAT 和 Case 的 sqlite 数据库的一些数据。但是我在使用这些功能时遇到了问题。
首先让我们从我想要实现的目标开始:
我简化了我的 table 结构以更好地指出问题:1 个简单的 table 有两列:名称(字符)、is_controlled(布尔值)。
此 SQL 请求计算所需结果:
SELECT
SUM(is_controlled),
GROUP_CONCAT(CASE WHEN is_controlled = 1 THEN name ELSE NULL END, ':') as controlled,
GROUP_CONCAT(CASE WHEN is_controlled = 0 THEN name ELSE NULL END, ':') as not_controlled
FROM component;
输出(这是我对 peewee 的期望):
2
comp1:comp3
comp2
这是一个可以测试我的问题的脚本:
from peewee import *
db = SqliteDatabase('test.db')
class Component(Model):
name = CharField()
is_controlled = BooleanField()
class Meta:
database = db
raw_data = [
{'name': 'comp1', 'is_controlled': True},
{'name': 'comp2', 'is_controlled': False},
{'name': 'comp3', 'is_controlled': True},
]
db.connect()
# Populate database
db.create_tables([Component])
for item in raw_data:
Component.get_or_create(**item)
res = Component.select(
fn.Sum(Component.is_controlled).alias('controlled_count'),
fn.GROUP_CONCAT(Case(None, [((Component.is_controlled == True), Component.name)], None), ':').alias('controlled'),
fn.GROUP_CONCAT(Case(None, [((Component.is_controlled == False), Component.name)], None), ':').alias('not_controlled')
)
print res[0].controlled_count
print res[0].controlled
print res[0].not_controlled
db.close()
如您所见,数据结构很简单(我最大限度地简化了示例)。输出是:
2
:comp3:
:
我检查了 peewee 生成的 SQL 查询(使用 res.sql()),它看起来像这样:
sql = 'SELECT Sum("t1"."is_controlled") AS "controlled_count", GROUP_CONCAT(CASE WHEN ("t1"."is_controlled" = ?) THEN ? END, "t1"."name") AS "controlled", GROUP_CONCAT(CASE WHEN ("t1"."is_controlled" = ?) THEN ? END, "t1"."name") AS "not_controlled" FROM "component" AS "t1"'
params = [True, ':', False, ':']
我们可以看到在 peewee 生成的 SQL 请求中缺少 ELSE NULL 部分。我已经尝试了几种方法,比如调整给 Case 函数的参数,但我无法让它正常工作。
如何正确使用 peewee 才能获得与使用 SQL 相同的结果?
(我正在使用 python 2.7.15 和 peewee 3.6.4 ans sqlite 3.19.4)
Case
函数的签名提供了一条线索:
def Case(predicate, expression_tuples, default=None):
在代码内部,它检查:
if default is not None:
clauses.extend((SQL('ELSE'), default))
所以,当你通过 None
时,它与 "empty/unspecified" 的情况没有区别,Peewee 会忽略它。
作为解决方法,您可以将 SQL('NULL')
指定为默认值。或者你可以使用一个空字符串,虽然我不确定你是否依赖于 group-concat 的某些行为与空值,所以这可能不起作用?
我正在尝试使用 peewee 来获取和格式化来自使用 GROUP_CONCAT 和 Case 的 sqlite 数据库的一些数据。但是我在使用这些功能时遇到了问题。
首先让我们从我想要实现的目标开始:
我简化了我的 table 结构以更好地指出问题:1 个简单的 table 有两列:名称(字符)、is_controlled(布尔值)。 此 SQL 请求计算所需结果:
SELECT
SUM(is_controlled),
GROUP_CONCAT(CASE WHEN is_controlled = 1 THEN name ELSE NULL END, ':') as controlled,
GROUP_CONCAT(CASE WHEN is_controlled = 0 THEN name ELSE NULL END, ':') as not_controlled
FROM component;
输出(这是我对 peewee 的期望):
2
comp1:comp3
comp2
这是一个可以测试我的问题的脚本:
from peewee import *
db = SqliteDatabase('test.db')
class Component(Model):
name = CharField()
is_controlled = BooleanField()
class Meta:
database = db
raw_data = [
{'name': 'comp1', 'is_controlled': True},
{'name': 'comp2', 'is_controlled': False},
{'name': 'comp3', 'is_controlled': True},
]
db.connect()
# Populate database
db.create_tables([Component])
for item in raw_data:
Component.get_or_create(**item)
res = Component.select(
fn.Sum(Component.is_controlled).alias('controlled_count'),
fn.GROUP_CONCAT(Case(None, [((Component.is_controlled == True), Component.name)], None), ':').alias('controlled'),
fn.GROUP_CONCAT(Case(None, [((Component.is_controlled == False), Component.name)], None), ':').alias('not_controlled')
)
print res[0].controlled_count
print res[0].controlled
print res[0].not_controlled
db.close()
如您所见,数据结构很简单(我最大限度地简化了示例)。输出是:
2
:comp3:
:
我检查了 peewee 生成的 SQL 查询(使用 res.sql()),它看起来像这样:
sql = 'SELECT Sum("t1"."is_controlled") AS "controlled_count", GROUP_CONCAT(CASE WHEN ("t1"."is_controlled" = ?) THEN ? END, "t1"."name") AS "controlled", GROUP_CONCAT(CASE WHEN ("t1"."is_controlled" = ?) THEN ? END, "t1"."name") AS "not_controlled" FROM "component" AS "t1"'
params = [True, ':', False, ':']
我们可以看到在 peewee 生成的 SQL 请求中缺少 ELSE NULL 部分。我已经尝试了几种方法,比如调整给 Case 函数的参数,但我无法让它正常工作。
如何正确使用 peewee 才能获得与使用 SQL 相同的结果?
(我正在使用 python 2.7.15 和 peewee 3.6.4 ans sqlite 3.19.4)
Case
函数的签名提供了一条线索:
def Case(predicate, expression_tuples, default=None):
在代码内部,它检查:
if default is not None:
clauses.extend((SQL('ELSE'), default))
所以,当你通过 None
时,它与 "empty/unspecified" 的情况没有区别,Peewee 会忽略它。
作为解决方法,您可以将 SQL('NULL')
指定为默认值。或者你可以使用一个空字符串,虽然我不确定你是否依赖于 group-concat 的某些行为与空值,所以这可能不起作用?