SAS — подсчет событий, происходящих в течение заданного периода времени

Я пытаюсь написать простой код для подсчета количества услуг, предоставляемых каждый год для различных поставщиков, на основе одного исходного столбца. В идеале мой вывод будет упрощенно выглядеть примерно так:

Входные данные будут выглядеть примерно так:

Prov_ID    Name    Service_Cd  Date
A          Joe     B2           02JUN2012
A          Joe     C9           04OCT2013
A          Joe     B2           12JUL2014
B          Steve   A1           12MAR2012
B          Steve   E4           20OCT2013
C          Tom     B10          23SEP2012
...        ...     ...          ...
...        ...     ...          ...

И так далее, с целью иметь уникальный идентификатор поставщика, общее количество оказанных услуг, а затем итоговые суммы за 2012, 2013, 2014 годы.

ProvID  Name  Service_Count  2012_Count  2013_Count  2014_Count
A       Joe    12             4            6            2
B       Steve  15             5            5            5 
C       Tom    22             10           8            4

Приглушенная текущая версия кода, которую я написал для этой конкретной задачи, включает:

proc sql;
CREATE TABLE provider_detail as
    SELECT distinct(PROV_ID), COUNT(distinct Service_CD)AS Service_Count, COUNT (date between '01JAN2012'd AND '31DEC2012'd)AS 2012_Count,COUNT (date between '01JAN2013'd AND '31DEC2013'd)AS 2013_Count,COUNT (date between '01JAN2014'd AND '31DEC2014'd)AS 2014_Count
    FROM primary1
    Group BY PROV_ID;
    run;

Но при этом я получаю одинаковое количество в каждом столбце. Любая помощь будет принята с благодарностью, поскольку я новичок в SAS и, так сказать, все еще изучаю веревки. Благодарю вас!


person Brad    schedule 06.05.2015    source источник
comment
Замените count() на sum() (кроме первого), и он будет работать (также пусть имена выходных переменных начинаются с буквы или подчеркивания и заменяют run; на quit;)   -  person DaBigNikoladze    schedule 07.05.2015
comment
Я думаю, что некоторая путаница здесь связана с тем, что никто не знает, как на самом деле выглядят ваши входные данные. Это может помочь опубликовать образец набора входных данных.   -  person DWal    schedule 07.05.2015
comment
Спасибо, @DaBigNikoladze изменение счета на сумму сработало.   -  person Brad    schedule 07.05.2015
comment
@DWal, я согласен, что должен был сделать это изначально, я добавлю пример кода ввода, чтобы другие могли его использовать.   -  person Brad    schedule 07.05.2015


Ответы (1)


Ваш бит date between в первую очередь неверен. Это то, что SAS, как правило, будет очень рад сделать для вас в PROC, хотя SQL также не особенно сложен.

В SQL одним из вариантов является использование case when для получения такого рода информации. См. что-то вроде следующего:

proc sql;
    select make, count(distinct model) as total, 
        count(distinct case when driveTrain='Rear' then Model else ' ' end) as RWD,
        count(distinct case when driveTrain='Front' then model else ' ' end) as FWD,
        count(distinct case when driveTrain='All' then model else ' ' end) as AWD        
    from sashelp.cars
    group by make;
quit;

case when в основном if в sql: на уровне строки он делает что-то условно, а затем помещает это в результат выбора.

Конечно, в SAS это проще сделать с помощью процедуры табуляции (proc freq, proc means, proc tabulate):

proc tabulate data=sashelp.cars;
    class make drivetrain;
    tables make,drivetrain*n;
run;

Как отмечено ниже, это требует отдельного рассмотрения уникальности.

person Joe    schedule 06.05.2015
comment
Бит date between не является неправильным, он просто должен быть внутри функции sum() вместо count(). Таким образом, он суммирует логическое условие 0/1, подсчитывая количество услуг между желаемыми датами. Это более гибко, чем подготовка group by переменных, например, вы можете вести подсчет внутри перекрывающихся интервалов дат. - person DaBigNikoladze; 07.05.2015
comment
Если комбинации make/model не уникальны, то эта таблица proc не даст желаемых результатов. Если марка/модель уникальны, то предложения distinct не нужны, и вы можете просто использовать count(1) as total, sum(driveTrain='Rear') as RWD,..., как предлагает BDN. Это будет соответствовать приведенной выше процедуре. - person DWal; 07.05.2015
comment
@DaBigNikoladze Да, это еще один вариант - мне так больше нравится, я нахожу case when более гибким для своих нужд. Я не хотел сказать, что date between невозможно заставить работать, просто проблема заключалась в этом (как вы заметили, sum сработает). - person Joe; 07.05.2015
comment
@DWal Абсолютно, и я хотел оставить это как примечание - отвлекся на работу и забыл, прежде чем опубликовать. Спасибо за напоминание. - person Joe; 07.05.2015