ltv 模型

This commit is contained in:
wuaho 2021-07-27 14:30:23 +08:00
parent a2d08b35e9
commit db2262ec0b
2 changed files with 130 additions and 54 deletions

View File

@ -20,13 +20,36 @@ from models.x_analysis import XAnalysis
router = APIRouter() router = APIRouter()
@router.post("/overview") @router.post("/ltv_model_sql")
async def event_model_sql( async def ltv_model_sql(
request: Request, request: Request,
game: str, game: str,
analysis: XAnalysis = Depends(XAnalysis), analysis: XAnalysis = Depends(XAnalysis),
current_user: schemas.UserDB = Depends(deps.get_current_user) current_user: schemas.UserDB = Depends(deps.get_current_user)
) -> schemas.Msg: ) -> schemas.Msg:
""" 数据总览 """ """ ltv模型sql """
sql = analysis.to_sql() await analysis.init()
sql = analysis.ltv_model_sql()
return schemas.Msg(code=0, msg='ok', data=sql) return schemas.Msg(code=0, msg='ok', data=sql)
@router.post("/ltv_model")
async def ltv_model_sql(
request: Request,
game: str,
analysis: XAnalysis = Depends(XAnalysis),
ckdb: CKDrive = Depends(get_ck_db),
current_user: schemas.UserDB = Depends(deps.get_current_user)
) -> schemas.Msg:
""" ltv模型sql """
await analysis.init()
sql = analysis.ltv_model_sql()
df = await ckdb.query_dataframe(sql)
df.fillna(0, inplace=True)
df.rename(columns={'date': '注册日期', 'cnt1': '角色数'}, inplace=True)
data = {
'titel': df.columns.tolist(),
'rows': df.values.tolist()
}
return schemas.Msg(code=0, msg='ok', data=data)

View File

@ -1,5 +1,6 @@
from typing import Tuple from typing import Tuple
import arrow
import sqlalchemy as sa import sqlalchemy as sa
import json import json
@ -9,68 +10,120 @@ import pandas as pd
from sqlalchemy import func, or_, and_, not_, MetaData from sqlalchemy import func, or_, and_, not_, MetaData
import crud
import schemas import schemas
from core.config import settings from core.config import settings
from db import get_database
from db.redisdb import get_redis_pool, RedisDrive from db.redisdb import get_redis_pool, RedisDrive
class XAnalysis: class XAnalysis:
def __init__(self, data_in: schemas.Overview, game: str): def __init__(self, data_in: schemas.CkQuery, game: str):
self.data_in = data_in self.data_in = data_in
self.game = game self.game = game
self.event_view = dict()
self.events = []
def to_sql(self): self.global_filters = []
# 构建表
metadata = sa.MetaData(schema=self.game) def _get_global_filters(self):
tbl = sa.Table(f'overview', metadata, return self.event_view.get('filts') or []
sa.Column('date'),
sa.Column('#os'), async def init(self):
sa.Column('#bundle_id'), if self.data_in.report_id:
sa.Column('owner_name'), db = get_database()
sa.Column('channel'), report = await crud.report.get(db, id=self.data_in.report_id)
sa.Column('active_num'), self.event_view = report['query']['eventView']
sa.Column('new_account_num'), self.events = report['query']['events']
sa.Column('money'), e_days, s_days = self.event_view['recentDay'].split('-')
sa.Column('pay_account_num'), self.event_view['endTime'] = arrow.get().shift(days=-int(e_days)).strftime('%Y-%m-%d 23:59:59')
sa.Column('new_pay_account_num'), self.event_view['startTime'] = arrow.get().shift(days=-int(s_days)).strftime('%Y-%m-%d 00:00:00')
sa.Column('new_money'),
)
# bundle_id_col = sa.Column('#bundle_id') else:
# channel_col = sa.Column('channel') self.event_view = self.data_in.eventView
# owner_name_col = sa.Column('owner_name') self.events = self.data_in.events
# os_col = sa.Column('#os')
# date_col = sa.Column('date') self.global_filters = self._get_global_filters()
# active_num_col = sa.Column('active_num')
# new_account_num_col = sa.Column('new_account_num') def handler_filts(self):
where = []
for item in self.global_filters:
col = sa.Column(item['columnName'])
comparator = item['comparator']
ftv = item['ftv']
if comparator == '==':
if len(ftv) > 1:
where.append(or_(*[col == v for v in ftv]))
else:
where.append(col == ftv[0])
elif comparator == '>=':
where.append(col >= ftv[0])
elif comparator == '<=':
where.append(col <= ftv[0])
elif comparator == '>':
where.append(col > ftv[0])
elif comparator == '<':
where.append(col < ftv[0])
elif comparator == 'is not null':
where.append(col.isnot(None))
elif comparator == 'is null':
where.append(col.is_(None))
elif comparator == '!=':
where.append(col != ftv[0])
return where
def ltv_model_sql(self):
days = (arrow.get(self.event_view['endTime']).date() - arrow.get(self.event_view['startTime']).date()).days
select_ltv = []
sumpay = []
for i in range(1, days):
# select_ltv.append(func.round(sa.Column(f'sumpay_{i}') / sa.Column('cnt1'), 2).label(f'LTV{i}'))
select_ltv.append(
f"if(dateDiff('day', reg.date, now())<{i - 1}, '-',toString(round(sumpay_{i} / cnt1, 2))) AS LTV{i}")
sumpay.append(f"sum(if(dateDiff('day', a.date, b.date) < {i}, money, 0)) as sumpay_{i}")
# qry = sa.select(*select_ltv)
# select_ltv_str = str(qry.compile(compile_kwargs={"literal_binds": True}))
# select_ltv_str = select_ltv_str.split('SELECT ')[1]
sumpay_str = ','.join(sumpay)
select_ltv_str = ','.join(select_ltv)
where = [ where = [
getattr(tbl.c, 'date') >= self.data_in.sdate, sa.Column('date') > self.event_view['startTime'].split(' ')[0],
getattr(tbl.c, 'date') <= self.data_in.edate, sa.Column('date') <= self.event_view['endTime'].split(' ')[0]
] ]
where_ext = self.handler_filts()
if self.data_in.bundle_id: qry = sa.select().where(*where, *where_ext)
where.append(getattr(tbl.c, '#bundle_id').in_(self.data_in.bundle_id))
if self.data_in.channel:
where.append(getattr(tbl.c, '#bundle_id').in_(self.data_in.channel))
if self.data_in.owner_name:
where.append(getattr(tbl.c, 'owner_name').in_(self.data_in.owner_name))
if self.data_in.os:
where.append(getattr(tbl.c, '#os').in_(self.data_in.os))
qry = sa.select(getattr(tbl.c, 'date'), getattr(tbl.c, '#bundle_id'),
func.sum(getattr(tbl.c, 'active_num')).label('active_num'),
func.sum(getattr(tbl.c, 'new_account_num')).label('new_account_num'),
func.sum(getattr(tbl.c, 'pay_account_num')).label('pay_account_num'),
func.sum(getattr(tbl.c, 'money')).label('money'),
func.sum(getattr(tbl.c, 'new_pay_account_num')).label('new_pay_account_num'),
func.sum(getattr(tbl.c, 'new_money')).label('new_money'),
) \
.where(*where) \
.group_by(getattr(tbl.c, 'date'), getattr(tbl.c, '#bundle_id'))
sql = str(qry.compile(compile_kwargs={"literal_binds": True})) sql = str(qry.compile(compile_kwargs={"literal_binds": True}))
where_str = sql.split('WHERE ')[1]
sql = f"""SELECT toYYYYMMDD(reg.date) as date,
cnt1,
{select_ltv_str}
FROM (SELECT toDate(addHours(`#event_time`, `#zone_offset`)) as date, uniqExact(`#account_id`) cnt1
FROM {self.game}.event
where `#event_name` = 'create_role'
AND {where_str}
GROUP BY toDate(addHours(`#event_time`, `#zone_offset`))) as reg
left join
(select a.date,
{sumpay_str}
from (SELECT toDate(addHours(`#event_time`, `#zone_offset`)) as date, `#account_id`
FROM {self.game}.event
where `#event_name` = 'create_role'
and {where_str}) as a
left join (select `#account_id`, money, toDate(addHours(`#event_time`, `#zone_offset`)) as date
from {self.game}.event
where `#event_name` = 'rechargeGame') b
on a.`#account_id` = b.`#account_id`
group by a.date) log on reg.date = log.date
order by date
"""
print(sql) print(sql)
return sql return sql