2016-05-18 24 views
0

私は新しいSAS/SQLユーザーです。いくつかの行を列に転記する必要があるデータセットがあります。私はそれを行うためのより速くて簡単な方法があると思います。私はあなたにすべてのアドバイスをしたいと思います。私の例では、より良い私の問題を説明します。ここではSASまたはSQLの列への行の転置

は、私が持っているデータセットです。

Month ID  Car  Claim_Type Cost_of_claim 
    1 1243 Ferrari Collision  12,000 
    2 6437 Peugeot Fire   50,000 
    5 0184 Citroen Stole   3,000 
    9 1930 Fiat  Medical   1,000 
    3 2934 GM   Liability  20,000 

そして、私はそのようなデータセットを作成する必要があります。

Month ID  Car Collision Fire Stole Medical Liability 
1 1243 Ferrari 12,000  0  0  0   0 
2 6437 Peugeot  0  50,000  0  0   0   
5 0184 Citroen  0   0  3,000 0   0 
9 1930 Fiat   0   0  0  1,000  0 
3 2934 GM   0   0  0  0  20,000 

私は列にいくつかの行を転置しました...

私は、新しいデータセットを作成するために何かを考えていました。

proc sql; 
select Month, ID, CAR 
    case when Claim_Type = 'Collision' then Cost_of_claim end Collision, 
    case when Claim_Type = 'Fire'  then Cost_of_claim end Fire, 
    case when Claim_Type = 'Stole'  then Cost_of_claim end Stole, 
    case when Claim_Type = 'Medical' then Cost_of_claim end Medical, 
    case when Claim_Type = 'Liability' then Cost_of_claim end Liability 
from my_table; 

問題は、膨大な量のデータがあり、この方法があまり効率的でない可能性があるということです。また、私のデータセットでは、はるかに多くの列と行があり、コードを維持するのは簡単ではないと思われるので、case whenステートメントにすべての可能性を入力する必要はありません。

誰かが解決方法を教えてもらえますか?

答えて

0

動的SQLとピボットを試すことはできますが、パフォーマンスは所有するクレームの種類によって異なります。

create table #mytable (Month int, ID int, Car varchar(20), Claim_Type varchar(20), Cost_of_claim int) 

insert into #mytable values 
(1, 1243, 'Ferrari', 'Collision', 12000) 
, (2, 6437, 'Peugeot', 'Fire', 50000) 
, (5, 184, 'Citroen', 'Stole', 3000) 
, (9, 1930, 'Fiat', 'Medical', 1000) 
, (3, 2934, 'GM', 'Liability', 20000) 
, (12, 4455, 'Ford', 'Theft', 20) 


DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT ',' + QUOTENAME(Claim_Type) 
        from #mytable 
        group by Claim_Type 
        order by Claim_Type 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = N'SELECT ' + 'month,id,car,' + @cols + N' from 
      (
       select month,id, car, Cost_of_claim, Claim_Type 
       from #mytable    
      ) x 
      pivot 
      (
       max(Cost_of_claim) 
       for Claim_Type in (' + @cols + N') 
      ) p 
      ' 

exec sp_executesql @query; 

drop table #mytable 
0

この方法では、すべての可能なclaim_typesとマクロ変数を移入し、あなたのコード例と同じ方法で変数を生成し、それらを介してループし、あなたはすべての可能なケースを入力する必要はありません。 "バックストップ"変数は、ループ内のコンマのために使用されます(SASは、プロキシSQLステップで最後のカンマの後に変数を1つも追加しないとエラーになります)。

data have; 
    input Month ID Car $12. Claim_Type $12. Cost_of_claim; 
    datalines; 
    1 1243 Ferrari Collision  12000 
    2 6437 Peugeot Fire   50000 
    5 0184 Citroen Stole   3000 
    9 1930 Fiat  Medical   1000 
    3 2934 GM   Liability  20000 
    ; 
run; 


%macro your_macro; 

    proc sql noprint; 
     select distinct claim_type into: list_of_claims separated by " " from have; 

     create table want (drop = backstop) as select 
      month, id, car, 
       %do i = 1 %to %sysfunc(countw(&list_of_claims.)); 
       %let this_claim = %scan(&list_of_claims., &i.); 
        case when claim_type = "&this_claim." then cost_of_claim else 0 end as &this_claim., 
       %end; 
      1 as backstop 
     from have; 
    quit; 

%mend your_macro; 

%your_macro; 
3

PROC TRANSPOSEは、必要な処理を行う必要があります。

data test; 
    input Month ID  Car $  Claim_Type : $12. Cost_of_claim; 
    cards; 
    1 1243 Ferrari Collision  12000 
    2 6437 Peugeot Fire   50000 
    5 0184 Citroen Stole   3000 
    9 1930 Fiat  Medical   1000 
    3 2934 GM   Liability  20000 
run; 

proc transpose data=test out=transposed; 
    by notsorted month notsorted id notsorted car; 
    var cost_of_claim; 
    id claim_type; 
run; 

出力データ・セットには、非対角ゼロを持っていませんが、あなたが本当にそれをしたい場合は、データの段階でそれらを追加することができます。

+0

NOTSORTEDは、DESCENDINGオプションとは異なり、BY文のすべてに適用されます。私は通常それを最後に置く。 –

関連する問題