依据注册日期查询出对应渠道留存

实现效果(数据为测试数据)


难点:sql 编写  (分组以及inner join  union all 的运用)

            登录表按月表之后的查询(30天  需要考虑到月份31日  二月份 28日

实现sql:

查询日期在同一月份(eg: 6.1 -6.30)

select day,count(uid) as total,channel from (select date_format(l.time,'%Y%m%d') as day,r.uid,r.`channel` from `d_user_register201705` as r  INNER JOIN  `d_user_login201706` as l on r.uid=l.uid where r.time>='2017-05-31 00:00:00' and r.time<='2017-05-31 23:59:59' and l.type=0 and l.time>='2017-06-01 00:00:00' and l.time<='2017-06-30 23:59:59' group by day,r.uid ) as tmp group by day,channel

查询日期跨一个自然月(eg:06.6-07.6)

select day,count(uid) as total,channel from (select date_format(l1.time,'%Y%m%d') as day,r.uid,r.`channel` from `d_user_register201706` as r  INNER JOIN  `d_user_login201706` as l1  on r.uid=l1.uid where r.time>='2017-06-05 00:00:00'  and r.time<='2017-06-05 23:59:59' and l1.type=0 and l1.time>='2017-06-06 00:00:00'  and l1.time<='2017-07-05 23:59:59' group by day,uid union all  select date_format(l2.time,'%Y%m%d') as day,r.uid,r.`channel` from `d_user_register201706` as r  INNER JOIN  `d_user_login201707` as l2  on r.uid=l2.uid where r.time>='2017-06-05 00:00:00'  and r.time<='2017-06-05 23:59:59'  and l2.type=0 and l2.time>='2017-06-06 00:00:00'  and l2.time<='2017-07-05 23:59:59' group by day,uid) as tt group by day,channel order by day desc

查询日期在跨越2月份(eg:1.31-3.1) 按月分表容易出现错误

select day,count(uid) as total,channel from (select date_format(l1.time,'%Y%m%d') as day,r.uid,r.`channel` from `d_user_register201701` as r INNER JOIN `d_user_login201701` as l1 on r.uid=l1.uid where r.time>='2017-01-30 00:00:00' and r.time<='2017-01-30 23:59:59' and l1.type=0 and l1.time>='2017-01-31 00:00:00' and l1.time<='2017-03-01 23:59:59' group by day,uid union all select date_format(l2.time,'%Y%m%d') as day,r.uid,r.`channel` from `d_user_register201701` as r INNER JOIN `d_user_login201702` as l2 on r.uid=l2.uid where r.time>='2017-01-30 00:00:00' and r.time<='2017-01-30 23:59:59' and l2.type=0 and l2.time>='2017-01-31 00:00:00' and l2.time<='2017-03-01 23:59:59' group by day,uid  union all select date_format(l3.time,'%Y%m%d') as day,r.uid,r.`channel` from `d_user_register201701` as r INNER JOIN `d_user_login201703` as l3 on r.uid=l3.uid where r.time>='2017-01-30 00:00:00' and r.time<='2017-01-30 23:59:59' and l3.type=0 and l3.time>='2017-01-31 00:00:00' and l3.time<='2017-03-01 23:59:59' group by day,uid 
) as tt group by day,channel


实现代码 :  (laravel 框架)

/**
     * 渠道留存对比
     * @param Request $request
     * @return $this
     */
    public function  channelDayKeep(Request $request){
        $data['time'] = $request->input('time',date('Y-m-d',strtotime('-1 day')));
        $time = strtotime($data['time']);
        for($i=$time+86400,$select_day=[];$i<=$time+30*86400;$i+=86400) $select_day[] = date('Ymd',$i);
        list($self_month,$select_start_month,$select_end_month,$select_start_day,$select_end_day) = [
            date('Ym',$time),
            substr(reset($select_day),0,6),
            substr(end($select_day),0,6),
            date('Y-m-d',strtotime(reset($select_day))),
            date('Y-m-d',strtotime(end($select_day)))
        ];
        if($time>=strtotime(date('Y-m-d'))) $data['time']=date('Y-m-d',strtotime('-1 days'));
        // 查询出当前日期成功渠道对应的渠道注册人数
        $channel_list = Channel::where('status','=',1)->lists('channel_name')->toArray();
        $channel = Channel::where('status','=',1)->lists('channel_describe','channel_name')->toArray();
        $register_channel_total = DB::connection('log')->table('d_user_register'.$self_month)
            ->select(DB::raw('count(uid) as total,channel'))
            ->where('time','>=',$data['time'].' 00:00:00')
            ->where('time','<=',$data['time'].' 23:59:59')
            ->whereRaw('binary trim(channel) in (\''.implode($channel_list,"','").'\')')
            ->groupBy('channel')->get();
        $register_channel_total = json_encode($register_channel_total);
        $register_channel_total = json_decode($register_channel_total,true);;
        //获取各个渠道30天内渠道登录人数
        if($select_end_month - $select_start_month==0){
            //当月
            $result = DB::connection('log')->select(DB::raw("select day,count(uid) as total,channel from (select date_format(l.time,'%Y%m%d') as day,
           r.uid,r.`channel` from `d_user_register{$self_month}` as r  INNER JOIN  `d_user_login{$select_start_month}` as l 
           on r.uid=l.uid where r.time>='{$data['time']} 00:00:00' and r.time<='{$data['time']} 23:59:59' and l.type=0 
           and l.time>='{$select_start_day} 00:00:00' and l.time<='{$select_end_day} 23:59:59' group by day,r.uid ) as tmp group by day,channel"));
        }elseif($select_end_month - $select_start_month==2){
            //2月28天
            $select_middle_month = $select_start_month+1;
            $result = DB::connection('log')->select(DB::raw(" select day,count(uid) as total,channel from (select date_format(l1.time,'%Y%m%d') as day,
             r.uid,r.`channel` from `d_user_register{$self_month}` as r  INNER JOIN  `d_user_login{$select_start_month}` as l1  
             on r.uid=l1.uid where r.time>='{$data['time']} 00:00:00'  and r.time<='{$data['time']} 23:59:59' and l1.type=0
           and l1.time>='{$select_start_day} 00:00:00'  and l1.time<='{$select_end_day} 23:59:59' group by day,uid union all 
            select date_format(l2.time,'%Y%m%d') as day,r.uid,r.`channel` from `d_user_register{$self_month}` as r  INNER JOIN  
          `d_user_login{$select_middle_month}` as l2  on r.uid=l2.uid where r.time>='{$data['time']} 00:00:00'  and r.time<='{$data['time']} 23:59:59' 
           and l2.type=0 and l2.time>='{$select_start_day} 00:00:00'  and l2.time<='{$select_end_day} 23:59:59' group by day,uid
          union all select date_format(l3.time,'%Y%m%d') as day,r.uid,r.`channel` from `d_user_register{$self_month}` as r  INNER JOIN 
          `d_user_login{$select_end_month}` as l3  on r.uid=l3.uid where r.time>='{$data['time']} 00:00:00'  and r.time<='{$data['time']} 23:59:59' 
          and l3.type=0 and l3.time>='{$select_start_day} 00:00:00'  and l3.time<='{$select_end_day} 23:59:59' group by day,uid) as tt group by day,channel"));
        }else{
            //相邻月
            $result = DB::connection('log')->select(DB::raw(" select day,count(uid) as total,channel from (select date_format(l1.time,'%Y%m%d') as day,
        r.uid,r.`channel` from `d_user_register{$self_month}` as r  INNER JOIN  `d_user_login{$select_start_month}` as l1  on r.uid=l1.uid 
         where r.time>='{$data['time']} 00:00:00'  and r.time<='{$data['time']} 23:59:59' and l1.type=0 and l1.time>='{$select_start_day} 00:00:00' 
          and l1.time<='{$select_end_day} 23:59:59' group by day,uid  union all select date_format(l3.time,'%Y%m%d') as day,r.uid,r.`channel` 
         from `d_user_register{$self_month}` as r  INNER JOIN  `d_user_login{$select_end_month}` as l3  
         on r.uid=l3.uid where r.time>='{$data['time']} 00:00:00'  and r.time<='{$data['time']} 23:59:59'
       and l3.type=0 and l3.time>='{$select_start_day} 00:00:00'  and l3.time<='{$select_end_day} 23:59:59' group by day,uid) 
       as tt group by day,channel"));
        }
        //对象转换数组
        $result = json_encode($result);
        $result = json_decode($result,true);
        foreach($result as $key=>$val){
            foreach($register_channel_total as $k=>$v){
                if($v['channel']==$val['channel']){
                    foreach($select_day as $j=>$g) {
                        if ($val['day'] == $g) {
                            $register_channel_total[$k]['son'][$j] = $val;continue;
                        }
                    }
                }
            }
        }
        return view('chart/channel/channelDayKeep')->with('channel_keep_day',$register_channel_total)->with('data',$data)->with('channel',$channel);
    }

视图:

<!DOCTYPE html>
<html lang="zh-cn">
@include('layouts.head')
<body>
<div class="container-fluid">
    <div class="panel panel-default">
        <div class="panel-heading">
            渠道留存对比
        </div>
        <div class="panel-body">
            <form action="{{action('Home\ChartController@channelDayKeep')}}" method="post" role="form">
                <div class="row">
                    <div class="col-md-3">
                        <div class="form-group form-inline">
                            <label for="">选择时间</label>
                            <input type="text" name="time" class="form-control form_date" value="{{$data['time']}}" readonly placeholder="请输入id"/>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="col-md-3 form-inline" >
                            <div class="form-group">
                                <input type="submit" class="btn btn-sm btn-primary" value="查询"/>
                            </div>
                        </div>
                    </div>
                </div>
            </form>
        </div>
    </div>
    <table class="table table-responsive table-bordered">
        <thead>
        <th>渠道</th>
        <th>渠道当天注册人数</th>
        <th>次日留存</th>
        <th>2日留存</th>
        <th>3日留存</th>
        <th>4日留存</th>
        <th>5日留存</th>
        <th>6日留存</th>
        <th>7日留存</th>
        <th>14日留存</th>
        <th>30日留存</th>
        </thead>
        <tbody>
        @if($channel_keep_day)
            @foreach($channel_keep_day as $key=>$value)
                <tr>
                    <td>{{$channel[$value['channel']]}}</td>
                    <td>{{$value['total']}}</td>
                    @for($i=0;$i<=29;$i++)
                      @if($i<7||$i==13||$i==29)
                        @if(!isset($value['son'][$i]))
                            <td>0</td>
                        @else
                            <td>{{number_format($value['son'][$i]['total']/$value['total']*100,2,'.','')}}%</td>
                        @endif
                      @endif
                    @endfor
                </tr>
            @endforeach
        @else
            <tr>
                <td colspan="4">暂无数据</td>
            </tr>
        @endif
        </tbody>
    </table>
</div>
</body>
<script type="text/javascript">
    $('.form_date').datetimepicker({
        language: 'zh-CN', /*加载日历语言包,可自定义*/
        weekStart: 1, /*星期*/
        todayBtn: 0, /*当天*/
        autoclose: true,//选中之后自动隐藏日期选择框
        todayHighlight: 1, /*今天高亮显示*/
        startView: 2, /*4年3月2日1小时*/
        minView: 2, /*0分1小时2天*/
        format: 'yyyy-mm-dd',
        forceParse: 0,
        showMeridian:true
    });
</script>
</html>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值