2016-10-11 13 views
0

次の例にコードがあります。テーブルの列に応じて新しい列を作成します

legacy_id phone_type phone_number 
     1  f  1234567890 
     1  b  1233854100 
     1  f  4110256565 
     2  f  0707070770 
     2  b  7895120044 

データを次のようにしたいと思います。

legacy_id f_phone_number_1 b_phone_number_1 f_phone_number_2 
     1  1234567890  1233854100  4110256565 
     2  0707070770  7895120044 

私の最初のアプローチは動作しますが、これを行うのがより効率的であることが期待されていました。

Select fill.legacy_id, max(fill.f_phone_number_1),max(fill.b_phone_number_1),max(fill.f_phone_number_2) 
    from 
    (
     Select 
      a.legacy_id as legacy_id, a.phone_type as phone_type, 
      case 
       when a.phone_type = 'F' then a.phone_number and 
       dense_rank() over (partition by a.legacy_id, a.phone_type order by a.legacy_id, a.phone_type, a.phone_number) = 1 
       else null 
      end as f_phone_number_1, 
      case 
       when a.phone_type = 'F' then a.phone_number and 
       dense_rank() over (partition by a.legacy_id, a.phone_type order by a.legacy_id, a.phone_type, a.phone_number) = 2 
       else null 
      end as f_phone_number_2, 
      case 
       when a.phone_type = 'b' then a.phone_number and 
       dense_rank() over (partition by a.legacy_id, a.phone_type order by a.legacy_id, a.phone_type, a.phone_number) = 1 
       else null 
      end as b_phone_number_1 
     from table a 
     group by a.legacy_id, a.phone_type, a.phone_number 
    ) fill 
    group by fill.legacy_id 

もっと効率的なアプローチがありますか?

+0

が見えます。それはコードが少なく、スケーラブルですが、パフォーマンスは本当に依存します。 – scsimon

+0

テーブルに挿入するために選択されるので、スケーラブルではありません。私はピボットのアイデアが好きですが。 – LetUsSeng

+0

これをcodereview.stackexchange.comにも移動することができます – scsimon

答えて

0

あなたは動的SQLを使用してピボットすることができるはずのようにあなたがダイナミック行く必要がない場合は、条件付きの集約がトリックを行う必要があり

Declare @YourTable table (legacy_id int,phone_type varchar(25),phone_number varchar(25)) 
Insert Into @YourTable values 
(1,'f','1234567890'), 
(1,'b','1233854100'), 
(1,'f','4110256565'), 
(2,'f','0707070770'), 
(2,'b','7895120044') 

Select legacy_id 
     ,f_phone_number_1 = max(case when phone_type='f' and RowNr=1 Then phone_number else '' end) 
     ,b_phone_number_1 = max(case when phone_type='b' and RowNr=1 Then phone_number else '' end) 
     ,f_phone_number_2 = max(case when phone_type='f' and RowNr=2 Then phone_number else '' end) 
     ,b_phone_number_2 = max(case when phone_type='b' and RowNr=2 Then phone_number else '' end) 
From (
     Select * 
       ,RowNr=Row_Number() over (Partition By legacy_id,phone_type Order By (Select NULL)) 
     From @YourTable 
    ) A 
Group By legacy_id 

戻り

legacy_id f_phone_number_1 b_phone_number_1 f_phone_number_2 b_phone_number_2 
1   4110256565   1233854100   1234567890 
2   0707070770   7895120044  
+0

row_number()vs dense_rank()を使用するとパフォーマンスが向上しますか?現時点では、あなたのスクリプトは私のものと似ています。 – LetUsSeng

+0

@LetUsSengここではサブクエリで1回しかパスしません。試して傷つけることはできませんでした。 –

+0

ありがとう、私はこのショットを与えるでしょう。 – LetUsSeng

関連する問題