Как найти аналогично распределенную контрольную группу для тестовой группы в SQL? - PullRequest
0 голосов
/ 22 мая 2018

Задача довольно амбициозная.У меня около 50 тыс. Пользователей в месяц, и я хочу сопоставить аналогично распределенную группу контроля размера из полного пула пользователей, который составляет около 50 млн. Пользователей.Чтобы получить аналогичное распределение, у меня есть некоторые категориальные и числовые особенности.Категориальные черты будут просто inner joined.Числовые характеристики хотели бы округлить, но это составляет самую большую проблему.

Вот мой код:

with pl_subs as( -- in the cte I 
    select   al.*
  ,ROW_NUMBER() OVER(PARTITION BY 
      al.device_type
     ,al.report_mnth
     ,round(al.days_to_LAST_FLASH_DTTM, -1)
     ,round(al.LT_month, -1)
     ,round(al.REVC, -1)
     ,round(al.usg_in, -2)
     ,round(al.usg_AC, -1)
     ORDER BY null) AS RN
    from ai_pl_SUBS test_gr
    inner join  ai_SUBS_MONTH_CLR al 
    on al.cust_id = test_gr.cust_id
    and al.report_mnth = test_gr.REGISTERED_mnth
    where al.report_mnth  = '2017-11' and test_gr.REGISTERED_mnth = '2017-11'
)
sel count(1) -- just to count from (
sel al.cust_id, pl_subs.rn rn_pl
 ,ROW_NUMBER() OVER(PARTITION BY 
  pl_subs.device_type
 ,pl_subs.report_mnth
 ,pl_subs.MCID
 ,round(pl_subs.days_to_LF, -1)
 ,round(pl_subs.LT_month, -1)
 ,round(pl_subs.REVC, -1)
 ,round(pl_subs.usg_in, -2)
 ,round(pl_subs.usg_AC, -1)
 ORDER BY null) AS RN
from pl_subs
inner join ai_SUBS_MONTH_CLR al on 

-- 2 categorilal features
pl_subs.device_type =  al.device_type
and pl_subs.report_mnth = al.report_mnth

-- 5 numerical features
and round(pl_subs.days_to_LF, -1) = Round(al.days_to_LF, -1)
and round(pl_subs.LT_month, -1) = Round(al.LT_month, -1)
and round(pl_subs.REVC, -1) = Round(al.REVC, -1)
and round(pl_subs.usg_in, -2) = Round(al.usg_in, -2) 
and round(pl_subs.usg_AC, -1) = Round(al.usg_AC, -1) 
-- in the control group shouldnot be any cust_id from the test group
where al.cust_id not in (select cust_id from ai_pl_SUBS)
    and al.report_mnth = '2017-11'
    ) _out where rn <=  rn_pl 
-- each 7 features determines strata. So I need to have so many cust as I have in appropriate  strata in the test group

Люди в тестовой группе имеют более высокие числовые значения.В приведенном выше коде я округляю до десятков, поэтому промежуточная шпуля не будет слишком большой, но в результате я получаю только 36 тыс. Пользователей, а не 50 тыс., Как ожидалось.Я округляю до 2 - запрос не удастся с проблемой буферизации

Аналогично распределено - имеют одинаковое среднее значение для числовых значений

Есть ли ошибки кода?Как можно изменить код, чтобы клиент включался в страту несколько раз?

1 Ответ

0 голосов
/ 31 мая 2018

У моего кода выше есть некоторые проблемы:

1) round(pl_subs.LT_month , -1) = Round(al.LT_month , -1) - использование раундов по широко распространенным значениям в конечном итоге вызовет проблему при поиске клиента контроля пробника.Так что просто используйте варианты:

case when LT_month <= 4 then '0'
     when LT_month <= 8 then '1'
     when LT_month <= 12 then '2'
     when LT_month <= 17 then '3'
     when LT_month <= 24 then '4'
     when LT_month <= 36 then '5'
     when LT_month <= 56 then '6'
     when LT_month <= 83 then '7'
     when LT_month <= 96 then '8'

Предварительные вычисления и использование индексов сделают запрос довольно быстрым.Но не переусердствуйте

2) CTE должен содержать только страты + количество людей в этой группе:

 with pl_subs as( -- in the cte I 
        select  
          al.device_type
         ,al.report_mnth
-- rounds should be changed
         ,round(al.LT_month, -1)
         ,round(al.REVC, -1)
         ,round(al.usg_in, -2)
         ,round(al.usg_AC, -1)
, count(1) as rn
from ai_pl_SUBS test_gr
    inner join  ai_SUBS_MONTH_CLR al 
    on al.cust_id = test_gr.cust_id
    and al.report_mnth = test_gr.REGISTERED_mnth
    where al.report_mnth  = '2017-11' and test_gr.REGISTERED_mnth = '2017-11'
group by 1
)

sel subs_id, report_mnth from (
sel al.subs_id, al.report_mnth, pl_subs.max_rn max_rn
 ,ROW_NUMBER() OVER(PARTITION BY 
  pl_subs.device_type
 ,pl_subs.report_mnth
 ,pl_subs.segment
 ORDER BY null) AS RN
from pl_subs
inner join UAT_DM.ai_SUBS_MONTH_CLR al on 
pl_subs.device_type =  al.device_type
and pl_subs.report_mnth = al.report_mnth
and pl_subs.segment = al.segment
where al.subs_id not in (select subs_id from UAT_DM.ai_pl_SUBS)
    and al.report_mnth = '2017-11'

) _out where rn <=  max_rn;
...