From d2194403af4175bab533fa286a224f592882333c Mon Sep 17 00:00:00 2001 From: wuaho Date: Tue, 19 Oct 2021 13:59:28 +0800 Subject: [PATCH] =?UTF-8?q?ltv=E8=A1=A5=E5=85=85=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/api_v1/endpoints/xquery.py | 8 +++++ core/config.py | 14 +++++++++ models/x_analysis.py | 56 ++++++---------------------------- 3 files changed, 31 insertions(+), 47 deletions(-) diff --git a/api/api_v1/endpoints/xquery.py b/api/api_v1/endpoints/xquery.py index 23dcbe7..a845c00 100644 --- a/api/api_v1/endpoints/xquery.py +++ b/api/api_v1/endpoints/xquery.py @@ -52,7 +52,15 @@ async def ltv_model_sql( sql = res['sql'] quota = res['quota'] df = await ckdb.query_dataframe(sql) + if df.empty: + return schemas.Msg(code=-1, msg='查无数据') df.fillna(0, inplace=True) + for d in set(res['date_range']) - set(df['date']): + df.loc[len(df)] = '0' + df.loc[len(df) - 1, 'date'] = d + days = (pd.Timestamp.now().date() - d).days + df.loc[len(df) - 1, f'LTV{days + 2}':] = '-' + df.sort_values('date', inplace=True) df.rename(columns={'date': '注册日期'}, inplace=True) if quota == '#account_id': df.rename(columns={'cnt1': '角色数'}, inplace=True) diff --git a/core/config.py b/core/config.py index 3b4ef26..58a1530 100644 --- a/core/config.py +++ b/core/config.py @@ -38,6 +38,20 @@ class Settings(BaseSettings): 'password': 'gncPASUwpYrc' } + CK_CALC_SYMBO = { + '==': lambda col, val: col == val, + '>=': lambda col, val: col >= val, + '<=': lambda col, val: col <= val, + '>': lambda col, val: col > val, + '<': lambda col, val: col < val, + 'is not null': lambda col: col.isnot(None), + 'is null': lambda col: col.is_(None), + 'like': lambda col, val: col.like(f'%{val}%'), + 'not like': lambda col, val: col.notlike(f'%{val}%'), + 'in': lambda col, val: col.in_(val), + '!=': lambda col, val: col != val, + } + CK_TYPE_DICT = {"DateTime('UTC')": 'datetime', "Nullable(DateTime('UTC'))": 'datetime', "DateTime()": 'datetime', diff --git a/models/x_analysis.py b/models/x_analysis.py index 8713757..163e752 100644 --- a/models/x_analysis.py +++ b/models/x_analysis.py @@ -27,6 +27,8 @@ class XAnalysis: self.global_filters = [] self.account_filters = [] self.global_relation = 'and' + self.date_range = [] + self.ext_filters = (self.data_in.ext_filter.get('filts', []), self.data_in.ext_filter.get('relation', 'and')) def _get_global_filters(self): @@ -52,6 +54,8 @@ class XAnalysis: else: self.event_view = self.data_in.eventView self.events = self.data_in.events + for d in pd.date_range(self.event_view['startTime'],self.event_view['endTime'], freq='D', tz='UTC'): + self.date_range.append(d.date()) self.global_filters = self._get_global_filters() self.global_relation = self.event_view.get('relation', 'and') @@ -60,8 +64,6 @@ class XAnalysis: if 'data_where' in kwargs: self.account_filters = kwargs['data_where'].get(self.game, []) - - def handler_filts(self, *filters): """ :param filters: (filts:list,relation:str) @@ -120,56 +122,15 @@ class XAnalysis: if event_filter: event_filters.append(or_(*event_filter)) - return event_filters - # def handler_filts(self, filters): - # where = [] - # for item in 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]}%')) - # - # elif comparator == 'in': - # where.append(col.in_(ftv)) - # - # 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): + for i in range(1, days+2): # 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}") @@ -181,7 +142,7 @@ class XAnalysis: select_ltv_str = ','.join(select_ltv) where = [ - sa.Column('date') > self.event_view['startTime'].split(' ')[0], + sa.Column('date') >= self.event_view['startTime'].split(' ')[0], sa.Column('date') <= self.event_view['endTime'].split(' ')[0] ] qry = sa.select().where(*where) @@ -195,14 +156,14 @@ class XAnalysis: sql = str(qry.compile(compile_kwargs={"literal_binds": True})) where_order_str = sql.split('WHERE ')[1] - where_account = self.handler_filts((self.account_filters, 'and'),self.ext_filters) + where_account = self.handler_filts((self.account_filters, 'and'), self.ext_filters) where_account_str = 1 if where_account: qry = sa.select().where(*where_account) sql = str(qry.compile(compile_kwargs={"literal_binds": True})) where_account_str = sql.split('WHERE ')[1] - sql = f"""SELECT toString(reg.date) as date, + sql = f"""SELECT reg.date as date, cnt1, {select_ltv_str} FROM (SELECT toDate(addHours(`#event_time`, `#zone_offset`)) as date, uniqExact(`{quota}`) cnt1 @@ -228,4 +189,5 @@ class XAnalysis: return {'sql': sql, 'quota': quota, 'start_date': self.event_view['startTime'][:10], 'end_date': self.event_view['endTime'][:10], + 'date_range': self.date_range }