149 lines
5.6 KiB
Python
149 lines
5.6 KiB
Python
from typing import Tuple
|
|
|
|
import arrow
|
|
import sqlalchemy as sa
|
|
import json
|
|
|
|
from fastapi import Depends
|
|
|
|
import pandas as pd
|
|
|
|
from sqlalchemy import func, or_, and_, not_, MetaData
|
|
|
|
import crud
|
|
import schemas
|
|
from core.config import settings
|
|
from db import get_database
|
|
from db.redisdb import get_redis_pool, RedisDrive
|
|
|
|
|
|
class XAnalysis:
|
|
def __init__(self, data_in: schemas.CkQuery, game: str):
|
|
self.data_in = data_in
|
|
self.game = game
|
|
self.event_view = dict()
|
|
self.events = []
|
|
|
|
self.global_filters = []
|
|
|
|
def _get_global_filters(self):
|
|
return self.event_view.get('filts') or []
|
|
|
|
async def init(self):
|
|
if self.data_in.report_id:
|
|
db = get_database()
|
|
report = await crud.report.get(db, id=self.data_in.report_id)
|
|
self.event_view = report['query']['eventView']
|
|
self.events = report['query']['events']
|
|
try:
|
|
e_days = self.event_view['e_days']
|
|
s_days = self.event_view['s_days']
|
|
except:
|
|
# 兼容以前的
|
|
e_days, s_days = self.event_view['recentDay'].split('-')
|
|
# self.event_view['endTime'] = arrow.get().shift(days=-int(e_days)+1).strftime('%Y-%m-%d 23:59:59')
|
|
# self.event_view['startTime'] = arrow.get().shift(days=-int(s_days)+1).strftime('%Y-%m-%d 00:00:00')
|
|
self.event_view['endTime'] = arrow.get().shift(days=-int(e_days)).strftime('%Y-%m-%d 23:59:59')
|
|
self.event_view['startTime'] = arrow.get().shift(days=-int(s_days)).strftime('%Y-%m-%d 00:00:00')
|
|
|
|
|
|
else:
|
|
self.event_view = self.data_in.eventView
|
|
self.events = self.data_in.events
|
|
|
|
self.global_filters = self._get_global_filters()
|
|
|
|
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])
|
|
elif comparator == 'not like':
|
|
where.append(col.notlike(f'%{ftv[0]}%'))
|
|
|
|
elif comparator == 'like':
|
|
where.append(col.like(f'%{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
|
|
quota = self.event_view['quota']
|
|
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 = [
|
|
sa.Column('date') > self.event_view['startTime'].split(' ')[0],
|
|
sa.Column('date') <= self.event_view['endTime'].split(' ')[0]
|
|
]
|
|
qry = sa.select().where(*where)
|
|
sql = str(qry.compile(compile_kwargs={"literal_binds": True}))
|
|
where_str = sql.split('WHERE ')[1]
|
|
|
|
where_order = self.handler_filts()
|
|
where_order_str = 1
|
|
if where_order:
|
|
qry = sa.select().where(*where_order)
|
|
sql = str(qry.compile(compile_kwargs={"literal_binds": True}))
|
|
where_order_str = sql.split('WHERE ')[1]
|
|
|
|
sql = f"""SELECT toString(reg.date) as date,
|
|
cnt1,
|
|
{select_ltv_str}
|
|
FROM (SELECT toDate(addHours(`#event_time`, `#zone_offset`)) as date, uniqExact(`{quota}`) cnt1
|
|
FROM {self.game}.event
|
|
where `#event_name` = 'create_account'
|
|
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, `{quota}`
|
|
FROM {self.game}.event
|
|
where `#event_name` = 'create_account'
|
|
and {where_str}) as a
|
|
left join (select `{quota}`, unitPrice/100 as money, toDate(addHours(`#event_time`, `#zone_offset`)) as date
|
|
from {self.game}.event
|
|
where `#event_name` = 'pay' and {where_order_str}) b
|
|
on a.`{quota}` = b.`{quota}`
|
|
group by a.date) log on reg.date = log.date
|
|
order by date
|
|
"""
|
|
print(sql)
|
|
return {'sql': sql,'quota':quota}
|