SAS proc sql возвращает повторяющиеся значения группы по/порядку по переменным

У меня есть довольно простой SQL, который должен предоставлять 1 строку в квартал для каждого актива1. Вместо этого я получаю несколько строк для каждой группы.

Ниже приведен SQL, шаг данных SAS и некоторые выходные данные. Количество повторяющихся строк (в приведенных ниже данных 227708) равно Num_borrowers, что является количеством строк в активе1.

proc sql outobs=max;

create table table1 as
select 
    case 
        when period_dt ='01DEC2003'd then '2003Q4'
        when period_dt ='01DEC2004'd then '2004Q4'
        when period_dt ='01DEC2005'd then '2005Q4'
        when period_dt ='01DEC2006'd then '2006Q4'
        when period_dt ='01DEC2007'd then '2007Q4' 
        when period_dt ='01DEC2008'd then '2008Q4'
        when period_dt ='01DEC2009'd then '2009Q4'
        when period_dt ='01DEC2010'd then '2010Q4'
        when period_dt ='01DEC2011'd then '2011Q4'
        when period_dt ='01DEC2012'd then '2012Q4'
        when period_dt ='01DEC2013'd then '2013Q4'
        when period_dt ='01JUN2014'd then '2014Q2'   
    end as QTR,
    case 
        when MM_ASSET in ('C&I', 'Foreign', 'Leasing','Scored-WF','Scored-WB')  THEN 'C&I'
        when MM_ASSET='Construction' THEN 'Construction RE'
        when MM_ASSET='Mortgage-IP' THEN 'Income Producing RE'
        when MM_ASSET='Mortgage-OO' THEN 'Owner Occupied RE'
        when MM_ASSET='Mortgage-SF' THEN 'Mortgage-SF'
        when MM_ASSET='Unknown' THEN 'Other'
    end as asset1,
    count (period_dt) as Num_Borrowers, 
    exposure,
    co_itd,
    MM_NINEQTR_LOSS,
    MM_LIFE_LOSS
  from td_prod.OBLIGOR_COMBINED
  where period_dt in ('01DEC2003'd,'01DEC2004'd,'01DEC2005'd,'01DEC2006'd,'01DEC2007'd,'01DEC2008'd, '01DEC2009'd,'01DEC2010'd,'01DEC2011'd,'01DEC2012'd,'01DEC2013'd,'01JUN2014'd)
  and mm_asset in ('C&I','Foreign','Leasing','Construction','Mortgage-IP','Scored-WF','Scored-WB'
               'Mortgage-OO','Mortgage-SF','Unknown')
  group by 1,2
  order by 1,2;

quit;



data table2; set table1;

  Total_Exposure = exposure/1000000;
  if total_exposure = 0 then total_exposure=.;
  Total_Charge_Offs =co_itd/1000000;
  Total_9Q_Losses = MM_NINEQTR_LOSS/1000000;
  Total_Life_Losses = MM_LIFE_LOSS/1000000;
  avg_borrower_exp = total_exposure/num_borrowers;
  co_rate = total_charge_offs/total_exposure;
  life_lossR = Total_life_losses/total_exposure;
  nineQtr_lossR = total_9q_losses/total_exposure;

run;



*** sample of output data set ***;
qtr             asset1      num_borrowers
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708
2003Q4          C&I             227708

person pgrebus    schedule 27.08.2014    source источник
comment
какую базу данных вы используете здесь? Кажется, MySQL, вы выбираете больше полей в неагрегированной форме, чем группируете. Как ваша база данных знает, как обрабатывать несколько комбинаций воздействия, co_itd, MM_NINEQTR_LOSS, MM_LIFE_LOSS?   -  person Twelfth    schedule 28.08.2014
comment
Предположим, что вы используете SAS для каждого тега и PROC SQL. SAS SQL делает странную нестандартную вещь, не соответствующую стандарту ANSI, когда вы помещаете столбец в оператор select, который не входит в группу по столбцам и не вычисляется из агрегатной функции. Он возвращает каждую запись из исходной таблицы. И дает вам примечание в журнале, что этот шаг требует повторного слияния или что-то в этом роде. Иногда это повторное слияние полезно. Но я знал настоящих экспертов по SQL, которым не нравилась эта функция, и они избегали ее, как чумы. Многие базы данных выдали бы ошибку из такого оператора SELECT.   -  person Quentin    schedule 28.08.2014
comment
Тьфу, ты имеешь в виду, что MySQL не единственная вещь, которая делает это, SAS SQl тоже? Аргх!!!!!! Что происходит с этими языками, которые делают что-то не так, а не возвращают ошибку? В любом случае решение = выясните, что делать с этими 4 столбцами, которые вы исключили из предоставленного вами выборочного набора результатов.   -  person Twelfth    schedule 28.08.2014


Ответы (1)


Понял, что мой комментарий выше больше похож на ответ.

В SAS SQL в запросе с предложением group by, которое включает посторонние столбцы в операторе select (т. е. столбцы, не входящие в группу и не полученные из функции агрегирования), SAS «повторно объединяет» сводную статистику обратно в исходные данные. (с примечанием по этому поводу). Большинство SQL-запросов просто выдают ошибку. Ниже приведен пример:

data have;
  input gender $ age score;
  cards;
M 10 100
M 20 200
F 30 300
F 40 400
;
run;

proc sql;
  select gender, mean(age) as AvgAge, SCore
    from have
    group by gender
  ;
quit;

возвращает:

 gender      AvgAge     score
 F               35       300
 F               35       400
 M               15       100
 M               15       200

В вашем коде экспозиция, co_itd, MM_NINEQTR_LOSS и MM_LIFE_LOSS являются посторонними столбцами, что приводит к повторному объединению SAS.

Всякий раз, когда происходит повторное слияние, вы увидите следующее сообщение в журнале SAS:

ПРИМЕЧАНИЕ. Для запроса требуется повторное объединение сводной статистики с исходными данными.

См. раздел повторное объединение данных в документация SAS по функции сводки для более подробной информации.

person Quentin    schedule 28.08.2014
comment
Чтобы запретить повторное слияние, используйте параметр NOREMERGE proc sql или системный параметр NOSQLREMERGE. - person vasja; 24.07.2015