毎日の HiveSQL のちょっとしたコツ: データをクリーンアップし、同じグループ内のスパース フィールドに貴重なデータを入力する方法は?

0 ニーズ

1 需要分析

要件分析: 要件では、ランキングに従ってグループ内の最後から 2 番目の値を新しいフィールドとして見つけ、グループ内に最後から 2 番目の項目がない場合は現在の値を取る必要があります。

この質問が、グループ内でソートした後、最後から 2 番目を見つけることのみである場合、それは非常に単純であり、row_number() 関数を使用してそれを見つけることができますが、この質問の問題は、現在の値が必要であるということです。最後から2番目がない場合に保持されますが、エレガントに見つける方法は?

次の結果を取得するには、row_number() 関数を使用します。

with data as
         (select 111 as stu_id, 'class1' as class_name, 69 as score
          union all
          select 113 as stu_id, 'class1' as class_name, 74 as score
          union all
          select 112 as stu_id, 'class1' as class_name, 80 as score
          union all
          select 115 as stu_id, 'class1' as class_name, 93 as score
          union all
          select 114 as stu_id, 'class1' as class_name, 94 as score
          union all
          select 124 as stu_id, 'class2' as class_name, 70 as score
          union all
          select 121 as stu_id, 'class2' as class_name, 74 as score
          union all
          select 123 as stu_id, 'class2' as class_name, 78 as score
          union all
          select 122 as stu_id, 'class2' as class_name, 86 as score
          union all
          select 9999 as stu_id, 'class3' as class_name, 99 as score
         )
select stu_id
           , class_name
           , score
           , row_number() over (partition by class_name order by score desc ) rn1
          
      from data

上記の結果に基づいて、最後から 2 番目の値を取り出すにはどうすればよいですか? 上位層は、rn = 2 の場合にケースを使用し、効果を確認するためにスコア end を使用します。

with data as
         (select 111 as stu_id, 'class1' as class_name, 69 as score
          union all
          select 113 as stu_id, 'class1' as class_name, 74 as score
          union all
          select 112 as stu_id, 'class1' as class_name, 80 as score
          union all
          select 115 as stu_id, 'class1' as class_name, 93 as score
          union all
          select 114 as stu_id, 'class1' as class_name, 94 as score
          union all
          select 124 as stu_id, 'class2' as class_name, 70 as score
          union all
          select 121 as stu_id, 'class2' as class_name, 74 as score
          union all
          select 123 as stu_id, 'class2' as class_name, 78 as score
          union all
          select 122 as stu_id, 'class2' as class_name, 86 as score
          union all
          select 9999 as stu_id, 'class3' as class_name, 99 as score
         )
select stu_id
     , class_name
     , score
     , case when  rn1 = 2 then score end as  res
from (
         select stu_id
              , class_name
              , score
              , row_number() over (partition by class_name order by score desc ) rn1
              --, row_number() over (partition by class_name order by score  ) rn2
         from data
     ) t

最後から 2 番目の値が取り出されますが、それでも要件を満たしていません。要件では、このグループで生成されるフィールドの各行がこの値のすべてである必要があります。その方法は? これはデータクリーニングの手段でもあります.グループ内の空の値をグループ内の値で埋める方法は? max() 関数のウィンドウ処理: max() over(partition by group field)の手法を使用して、同じグループ内のすべての null 値が同じフィールドに割り当てられるようにします。SQL は次のとおりです。


with data as
         (select 111 as stu_id, 'class1' as class_name, 69 as score
          union all
          select 113 as stu_id, 'class1' as class_name, 74 as score
          union all
          select 112 as stu_id, 'class1' as class_name, 80 as score
          union all
          select 115 as stu_id, 'class1' as class_name, 93 as score
          union all
          select 114 as stu_id, 'class1' as class_name, 94 as score
          union all
          select 124 as stu_id, 'class2' as class_name, 70 as score
          union all
          select 121 as stu_id, 'class2' as class_name, 74 as score
          union all
          select 123 as stu_id, 'class2' as class_name, 78 as score
          union all
          select 122 as stu_id, 'class2' as class_name, 86 as score
          union all
          select 9999 as stu_id, 'class3' as class_name, 99 as score
         )
select stu_id
     , class_name
     , score
     , max(case when  rn1 = 2 then score end ) over(partition by class_name)   as  res
from (
         select stu_id
              , class_name
              , score
              , row_number() over (partition by class_name order by score desc ) rn1
              --, row_number() over (partition by class_name order by score  ) rn2
         from data
     ) t

結果の値がますます期待どおりになっていることがわかりますが、グループ内の 1 つの値のみを処理するにはどうすればよいでしょうか? ここでは、補助的な判断が必要です. min() =max() を使用して判断するか、percent_rank()=0 を使用して判断することができます. ここでは、min() =max() を使用して判断します.グループ内の値が一意である限り、最終的な SQL は次のようになります。

with data as
         (select 111 as stu_id, 'class1' as class_name, 69 as score
          union all
          select 113 as stu_id, 'class1' as class_name, 74 as score
          union all
          select 112 as stu_id, 'class1' as class_name, 80 as score
          union all
          select 115 as stu_id, 'class1' as class_name, 93 as score
          union all
          select 114 as stu_id, 'class1' as class_name, 94 as score
          union all
          select 124 as stu_id, 'class2' as class_name, 70 as score
          union all
          select 121 as stu_id, 'class2' as class_name, 74 as score
          union all
          select 123 as stu_id, 'class2' as class_name, 78 as score
          union all
          select 122 as stu_id, 'class2' as class_name, 86 as score
          union all
          select 9999 as stu_id, 'class3' as class_name, 99 as score
         )
select stu_id
     , class_name
     , score
     , max(case
               when rn1 != rn2 and rn1 = 2  --正序和倒序值不等 则取倒数第二的值 (rn1=2的值)
                   then score
               when rn1 = rn2 then score   --正序和倒序值相等 则取当前值
           end) over (partition by class_name) res
from (
         select stu_id
              , class_name
              , score
              , dense_rank()  over (partition by class_name order by score desc ) rn1
              , dense_rank() over (partition by class_name order by score) rn2 --用来辅助判断
             -- , percent_rank() over (partition by class_name order by score) pr --也可以采用该函数辅助判断(pr=0时候)
         from data
     ) t

2 まとめ

この記事では、実際の需要におけるケースを通じて、グループ内の null 値を埋めるスキルを完了する方法について説明します。ウィンドウを開くことによって、min()/max() オーバー (グループ化フィールドによるパーティション) を補足し、注意を払う必要があります。実際の状況に応じた max() 関数は、case when ステートメントを書くか、実際のニーズを満たす条件を構築します.この手法は、データの明確化のためによく使用されます.

おすすめ

転載: blog.csdn.net/godlovedaniel/article/details/129279641