peewee orm,如何将 SQL 转换为 orm
peewee orm, How to convert SQL to orm
小便:3.14.4
databse:postgresql
table定义
from peewee import *
from peewee import TextField
from playhouse.postgres_ext import DateTimeTZField
from model import BaseModel as Model, database
class AdAccount(Model):
account_id = BigIntegerField(primary_key=True)
bm_id = BigIntegerField(null=True, verbose_name="bm账号id", index=True)
bm_name = TextField(null=True, verbose_name="bm账号名称")
account_name = TextField(null=True, verbose_name="广告账号名称")
status = IntegerField(default=0, verbose_name="广告账号状态")
class Campaign(Model):
campaign_id = BigIntegerField(primary_key=True, verbose_name="广告系列Id")
campaign_name = CharField(null=True, verbose_name="广告系列名称")
status = CharField(null=True, verbose_name="广告系列状态")
effective_status = CharField(null=True, verbose_name="广告系列有效状态")
daily_budget = CharField(null=True, verbose_name="广告系列预算")
account_id = BigIntegerField(verbose_name="广告账号Id")
class AdSet(Model):
adset_id = BigIntegerField(null=True, verbose_name="广告组Id", index=True)
adset_name = CharField(verbose_name="广告组名称")
status = CharField(verbose_name="广告组状态")
effective_status = CharField(verbose_name="广告组有效状态")
daily_budget = CharField(null=True, verbose_name="每日预算")
optimization_goal = CharField(null=True, verbose_name="优化目标")
campaign_id = BigIntegerField(verbose_name="广告系列Id")
account_id = BigIntegerField(verbose_name="广告账号Id")
class Ad(Model):
ad_id = BigIntegerField(verbose_name="广告Id", index=True)
ad_name = CharField(verbose_name="广告名称")
# 广告
link = CharField(null=True, verbose_name="落地页链接")
# 状态
status = CharField(verbose_name="广告状态")
effective_status = CharField(verbose_name="广告有效状态")
adset_id = BigIntegerField(verbose_name="广告组Id")
account_id = BigIntegerField(verbose_name="广告账号Id")
# 成效数据表
class AdInsights(Model):
id = PrimaryKeyField()
ad_id = BigIntegerField(verbose_name="广告Id", index=True)
adset_id = BigIntegerField(verbose_name="广告组Id",index=True)
campaign_id = BigIntegerField(verbose_name="广告系列Id",index=True)
account_id = BigIntegerField(verbose_name="账号Id")
# 基础数据
impressions = FloatField(null=True, verbose_name="展示次数")
clicks = FloatField(null=True, verbose_name="链接点击次数")
unique_clicks = FloatField(null=True, verbose_name="链接点击人数")
spend = FloatField(null=True, verbose_name="花费")
reach = FloatField(null=True, verbose_name="覆盖人数")
frequency = FloatField(null=True, verbose_name="频次")
cpc = FloatField(null=True, verbose_name="单次点击成本")
cpm = FloatField(null=True, verbose_name="千人展现成本")
ctr = FloatField(null=True, verbose_name="点击率")
purchase_roas = FloatField(null=True, verbose_name="广告花费回报roas")
cpp = FloatField(null=True)
date = DateField(null=True, index=True) # 时间
create_time = DateTimeTZField()
update_time = DateTimeTZField()
# 成效 actions中获取
purchase = FloatField(null=True, verbose_name="购买")
add_to_cart = FloatField(null=True, verbose_name="加入购物车")
landing_page_view = FloatField(null=True, verbose_name="落地页浏览量")
omni_complete_registration = FloatField(null=True, verbose_name="注册")
app_install = FloatField(null=True, verbose_name="应用安装量")
# # 手动计算
# purchase_rate = FloatField(null=True, verbose_name="购买转化率") # 购买/点击量
# purchase_cost = FloatField(null=True, verbose_name="购买成本") # 花费/购买
# add_to_chart_rate = FloatField(null=True, verbose_name="加入购物车转化率") # 加入购物车/点击量
# add_to_cart_cost = FloatField(null=True, verbose_name="加入购物车成本") # 花费/加入购物车
# app_installs_rate = FloatField(null=True, verbose_name="应用安装转化率") # 应用安装量/点击量
# app_install_cost = FloatField(null=True, verbose_name="应用安装成本") # 花费/应用安装量
# # 其他
# cost_per_unique_click = TextField(null=True)
# cost_per_unique_action_type = TextField(null=True)
# cost_per_action_type = TextField(null=True)
# actions = TextField(null=True)
# unique_actions = TextField(null=True)
# action_values = TextField(null=True)
# cost_per_conversion = TextField(null=True)
# conversions = TextField(null=True)
# conversion_values = TextField(null=True)
if __name__ == '__main__':
database.create_tables([AdInsights, Ad, AdAccount, AdSet, Campaign])
我写的orm是这样的
ad_insights_alias = AdInsights.alias()
cte = ad_insights_alias.select(ad_insights_alias.adset_id, fn.SUM(ad_insights_alias.impressions),ad_insights_alias.date) \
.where(ad_insights_alias.date >= start_date, ad_insights_alias.date <= end_date).group_by(ad_insights_alias.adset_id, ad_insights_alias.date)
total = cte.count()
cte = cte.paginate(1, 10).alias('jq')
query = cte.select().join(AdSet,on=AdSet.adset_id==cte.c.adset_id).join(AdAccount,on=AdSet.account_id==AdAccount.account_id)
print(query)
'''
SELECT "t1"."id", "t1"."adset_id", "t1"."adset_name", "t1"."status",
"t1"."effective_status", "t1"."daily_budget", "t1"."optimization_goal",
"t1"."campaign_id", "t1"."account_id"
FROM "ad_set" AS "t1"
RIGHT OUTER JOIN
(SELECT "t2"."adset_id", SUM("t2"."impressions")
FROM "ad_insights" AS "t2"
WHERE (("t2"."date" >= '2021-08-04') AND ("t2"."date" <= '2021-08-05'))
GROUP BY "t2"."adset_id", "t2"."date" LIMIT 10 OFFSET 0
) AS "jq" ON ("jq"."adset_id" = "t1"."adset_id")
'''
我要的SQL是
SELECT * from (SELECT adset_id,date,SUM(clicks) FROM ad_insights GROUP BY adset_id,date limit 2 offset 1)作为 t1 在 t1.adset_id=t2.adset_id 加入 ad_set 作为 t2 在 t2.account_id=ad_account.account_id;
加入 ad_account
如何编写ORM
我已经简化了你的模型,这样我就可以解决这个问题。我相信这是有效的:
class Account(Base):
account_id = AutoField()
name = TextField()
class AdSet(Base):
adset_id = AutoField()
account = ForeignKeyField(Account)
class AdInsight(Base):
adset = ForeignKeyField(AdSet)
date = DateField()
clicks = IntegerField()
我创建了一些测试数据,以下查询对我来说运行良好:
# First create the subquery we will be joining against.
# You can uncomment the limit/offset as I had commented
# them out to simplify verifying the results.
subq = (AdInsight
.select(AdInsight.adset, AdInsight.date, fn.SUM(AdInsight.clicks).alias('total_clicks'))
.group_by(AdInsight.adset, AdInsight.date)
#.limit(2)
#.offset(1)
.alias('subq'))
# Then we'll select from AdSet, Account as well as from
# our subquery:
query = (AdSet
.select(Account, AdSet, subq.c.date, subq.c.total_clicks)
.join_from(AdSet, Account, on=(AdSet.account == Account.account_id))
.join_from(AdSet, subq, on=(AdSet.adset_id == subq.c.adset_id)))
# Now we can retrieve our data:
for row in query:
print(row.account.name, row.adinsight.date, row.adinsight.total_clicks)
# If you just want the plain row dicts, you can instead:
for row in query.dicts():
...
正在生成的 SQL 看起来像:
SELECT "t1"."account_id", "t1"."name", "t2"."adset_id",
"t2"."account_id", "subq"."date", "subq"."total_clicks"
FROM "adset" AS "t2"
INNER JOIN "account" AS "t1"
ON ("t2"."account_id" = "t1"."account_id")
INNER JOIN (
SELECT "t3"."adset_id", "t3"."date", SUM("t3"."clicks") AS "total_clicks"
FROM "adinsight" AS "t3"
GROUP BY "t3"."adset_id", "t3"."date" -- limit/offset would be here
) AS "subq"
ON ("t2"."adset_id" = "subq"."adset_id")
ad_insights_alias = AdInsights.alias()
cte = ad_insights_alias.select(ad_insights_alias.adset_id,
fn.SUM(ad_insights_alias.cliks).alias("cliks"),
ad_insights_alias.date).alias("date").where(ad_insights_alias.date >= start_date, ad_insights_alias.date <= end_date).group_by(ad_insights_alias.adset_id, ad_insights_alias.date)
total = cte.count()
cte = cte.paginate(1, 10).alias('jq')
query = cte.select_from(AdSet.adset_name,cte.c.impressions,AdAccount.bm_name).join(AdSet,on=AdSet.adset_id==cte.c.adset_id).join(AdAccount,on=AdSet.account_id==AdAccount.account_id)
print(query)
小便:3.14.4 databse:postgresql
table定义
from peewee import *
from peewee import TextField
from playhouse.postgres_ext import DateTimeTZField
from model import BaseModel as Model, database
class AdAccount(Model):
account_id = BigIntegerField(primary_key=True)
bm_id = BigIntegerField(null=True, verbose_name="bm账号id", index=True)
bm_name = TextField(null=True, verbose_name="bm账号名称")
account_name = TextField(null=True, verbose_name="广告账号名称")
status = IntegerField(default=0, verbose_name="广告账号状态")
class Campaign(Model):
campaign_id = BigIntegerField(primary_key=True, verbose_name="广告系列Id")
campaign_name = CharField(null=True, verbose_name="广告系列名称")
status = CharField(null=True, verbose_name="广告系列状态")
effective_status = CharField(null=True, verbose_name="广告系列有效状态")
daily_budget = CharField(null=True, verbose_name="广告系列预算")
account_id = BigIntegerField(verbose_name="广告账号Id")
class AdSet(Model):
adset_id = BigIntegerField(null=True, verbose_name="广告组Id", index=True)
adset_name = CharField(verbose_name="广告组名称")
status = CharField(verbose_name="广告组状态")
effective_status = CharField(verbose_name="广告组有效状态")
daily_budget = CharField(null=True, verbose_name="每日预算")
optimization_goal = CharField(null=True, verbose_name="优化目标")
campaign_id = BigIntegerField(verbose_name="广告系列Id")
account_id = BigIntegerField(verbose_name="广告账号Id")
class Ad(Model):
ad_id = BigIntegerField(verbose_name="广告Id", index=True)
ad_name = CharField(verbose_name="广告名称")
# 广告
link = CharField(null=True, verbose_name="落地页链接")
# 状态
status = CharField(verbose_name="广告状态")
effective_status = CharField(verbose_name="广告有效状态")
adset_id = BigIntegerField(verbose_name="广告组Id")
account_id = BigIntegerField(verbose_name="广告账号Id")
# 成效数据表
class AdInsights(Model):
id = PrimaryKeyField()
ad_id = BigIntegerField(verbose_name="广告Id", index=True)
adset_id = BigIntegerField(verbose_name="广告组Id",index=True)
campaign_id = BigIntegerField(verbose_name="广告系列Id",index=True)
account_id = BigIntegerField(verbose_name="账号Id")
# 基础数据
impressions = FloatField(null=True, verbose_name="展示次数")
clicks = FloatField(null=True, verbose_name="链接点击次数")
unique_clicks = FloatField(null=True, verbose_name="链接点击人数")
spend = FloatField(null=True, verbose_name="花费")
reach = FloatField(null=True, verbose_name="覆盖人数")
frequency = FloatField(null=True, verbose_name="频次")
cpc = FloatField(null=True, verbose_name="单次点击成本")
cpm = FloatField(null=True, verbose_name="千人展现成本")
ctr = FloatField(null=True, verbose_name="点击率")
purchase_roas = FloatField(null=True, verbose_name="广告花费回报roas")
cpp = FloatField(null=True)
date = DateField(null=True, index=True) # 时间
create_time = DateTimeTZField()
update_time = DateTimeTZField()
# 成效 actions中获取
purchase = FloatField(null=True, verbose_name="购买")
add_to_cart = FloatField(null=True, verbose_name="加入购物车")
landing_page_view = FloatField(null=True, verbose_name="落地页浏览量")
omni_complete_registration = FloatField(null=True, verbose_name="注册")
app_install = FloatField(null=True, verbose_name="应用安装量")
# # 手动计算
# purchase_rate = FloatField(null=True, verbose_name="购买转化率") # 购买/点击量
# purchase_cost = FloatField(null=True, verbose_name="购买成本") # 花费/购买
# add_to_chart_rate = FloatField(null=True, verbose_name="加入购物车转化率") # 加入购物车/点击量
# add_to_cart_cost = FloatField(null=True, verbose_name="加入购物车成本") # 花费/加入购物车
# app_installs_rate = FloatField(null=True, verbose_name="应用安装转化率") # 应用安装量/点击量
# app_install_cost = FloatField(null=True, verbose_name="应用安装成本") # 花费/应用安装量
# # 其他
# cost_per_unique_click = TextField(null=True)
# cost_per_unique_action_type = TextField(null=True)
# cost_per_action_type = TextField(null=True)
# actions = TextField(null=True)
# unique_actions = TextField(null=True)
# action_values = TextField(null=True)
# cost_per_conversion = TextField(null=True)
# conversions = TextField(null=True)
# conversion_values = TextField(null=True)
if __name__ == '__main__':
database.create_tables([AdInsights, Ad, AdAccount, AdSet, Campaign])
我写的orm是这样的
ad_insights_alias = AdInsights.alias()
cte = ad_insights_alias.select(ad_insights_alias.adset_id, fn.SUM(ad_insights_alias.impressions),ad_insights_alias.date) \
.where(ad_insights_alias.date >= start_date, ad_insights_alias.date <= end_date).group_by(ad_insights_alias.adset_id, ad_insights_alias.date)
total = cte.count()
cte = cte.paginate(1, 10).alias('jq')
query = cte.select().join(AdSet,on=AdSet.adset_id==cte.c.adset_id).join(AdAccount,on=AdSet.account_id==AdAccount.account_id)
print(query)
'''
SELECT "t1"."id", "t1"."adset_id", "t1"."adset_name", "t1"."status",
"t1"."effective_status", "t1"."daily_budget", "t1"."optimization_goal",
"t1"."campaign_id", "t1"."account_id"
FROM "ad_set" AS "t1"
RIGHT OUTER JOIN
(SELECT "t2"."adset_id", SUM("t2"."impressions")
FROM "ad_insights" AS "t2"
WHERE (("t2"."date" >= '2021-08-04') AND ("t2"."date" <= '2021-08-05'))
GROUP BY "t2"."adset_id", "t2"."date" LIMIT 10 OFFSET 0
) AS "jq" ON ("jq"."adset_id" = "t1"."adset_id")
'''
我要的SQL是
SELECT * from (SELECT adset_id,date,SUM(clicks) FROM ad_insights GROUP BY adset_id,date limit 2 offset 1)作为 t1 在 t1.adset_id=t2.adset_id 加入 ad_set 作为 t2 在 t2.account_id=ad_account.account_id;
加入 ad_account如何编写ORM
我已经简化了你的模型,这样我就可以解决这个问题。我相信这是有效的:
class Account(Base):
account_id = AutoField()
name = TextField()
class AdSet(Base):
adset_id = AutoField()
account = ForeignKeyField(Account)
class AdInsight(Base):
adset = ForeignKeyField(AdSet)
date = DateField()
clicks = IntegerField()
我创建了一些测试数据,以下查询对我来说运行良好:
# First create the subquery we will be joining against.
# You can uncomment the limit/offset as I had commented
# them out to simplify verifying the results.
subq = (AdInsight
.select(AdInsight.adset, AdInsight.date, fn.SUM(AdInsight.clicks).alias('total_clicks'))
.group_by(AdInsight.adset, AdInsight.date)
#.limit(2)
#.offset(1)
.alias('subq'))
# Then we'll select from AdSet, Account as well as from
# our subquery:
query = (AdSet
.select(Account, AdSet, subq.c.date, subq.c.total_clicks)
.join_from(AdSet, Account, on=(AdSet.account == Account.account_id))
.join_from(AdSet, subq, on=(AdSet.adset_id == subq.c.adset_id)))
# Now we can retrieve our data:
for row in query:
print(row.account.name, row.adinsight.date, row.adinsight.total_clicks)
# If you just want the plain row dicts, you can instead:
for row in query.dicts():
...
正在生成的 SQL 看起来像:
SELECT "t1"."account_id", "t1"."name", "t2"."adset_id",
"t2"."account_id", "subq"."date", "subq"."total_clicks"
FROM "adset" AS "t2"
INNER JOIN "account" AS "t1"
ON ("t2"."account_id" = "t1"."account_id")
INNER JOIN (
SELECT "t3"."adset_id", "t3"."date", SUM("t3"."clicks") AS "total_clicks"
FROM "adinsight" AS "t3"
GROUP BY "t3"."adset_id", "t3"."date" -- limit/offset would be here
) AS "subq"
ON ("t2"."adset_id" = "subq"."adset_id")
ad_insights_alias = AdInsights.alias()
cte = ad_insights_alias.select(ad_insights_alias.adset_id,
fn.SUM(ad_insights_alias.cliks).alias("cliks"),
ad_insights_alias.date).alias("date").where(ad_insights_alias.date >= start_date, ad_insights_alias.date <= end_date).group_by(ad_insights_alias.adset_id, ad_insights_alias.date)
total = cte.count()
cte = cte.paginate(1, 10).alias('jq')
query = cte.select_from(AdSet.adset_name,cte.c.impressions,AdAccount.bm_name).join(AdSet,on=AdSet.adset_id==cte.c.adset_id).join(AdAccount,on=AdSet.account_id==AdAccount.account_id)
print(query)