2017-02-11 20 views
1

私はテーブルpeople(特に)フィールドgivenNamegenderを持っています。私はgender=NULLですべての行を更新するには、他の行に基づいて推測するのが最適です。複雑なSQLクエリが必要

"John", "male" 
"Jane", "female" 
"Sam", NULL 
"Alex", "female" 
"Jack", NULL 
... 

それはかどうかは不明で残っているのに対し、だから、ジョンが正しくジェーンは、女性として、男性として識別されています。私は、次の変更を生成したいtehの次の行

"John", NULL 
"Jane", NULL 
"Sam", NULL 
"Alex", NULL 
"Jack", NULL 
"John", "male" 
"John", "male" 
"Jane", "female" 
"Sam", "female" 
"Sam", "male" 
"Alex", "female" 

がある場合は、され SamはSamanthaまたはSamuelです。私は私のアプローチの欠点を認識しています(つまり、Alexは実際には男性かもしれません。よく知られている男性名Jackはそのように認識されません)。でも、私の目標が単一のSQLクエリで達成できるかどうか疑問です。

それが(例えば、「サム」など)混合例がなかったら、私はUPDATE people A, people B SET A.gender = B.gender WHERE A.givenName=B.givenName AND A.gender IS NULL and B.gender IS NOT NULLはそれを行うべきであると仮定...

+0

私はそれについて単一の質問についてはわかりません。まず、 "givenname"と "gender(nullではない)"というグループが必要です... "givenname"で2番目のレベルのグループの後にCOUNT(*)= 1(これは男性/女性の両方ではないことを意味します。その後、あなたはテーブル内に "曖昧さのないジェンダーの名前のマップ"しか持たないでしょう。 – laser

+0

@laser言い換えれば、(人間の読者とメンテナーにとっては)おそらく、曖昧な名前? –

+0

はい、私はそうだと思います。そうでなければ、新しい読者のためにロケット科学になるでしょう=) – laser

答えて

1

あなたが持っnullでないに値を選択することによりdinamically geratedテーブルを使用することができますcount = 1

UPDATE people A 
    INNER JOIN (select name, max(gender) gender 
       from people 
       where gender is not null 
       group by name 
       having count(gender)=1) t on t.name = a.name 
    set a.gender = t.gender 
+0

あなたの質問は性別が既に設定されている(つまり、 WHERE-condition 'AND a.gender IS NULL'を追加する方が良いでしょうか、パフォーマンスには問題ありませんか? (また、私は混乱しています: 't.name = a.name'と' a.name = t.name'は冗長ではありませんか?) –

+0

は、名前の一致するすべての行を修正する必要があります.. ..性別に関して)性別が異なる1つの名前のみを選択する必要があります。(条件が冗長な場合は元に戻します)性別が1つしかない場合は、更新は必要ありません。パフォーマンスは不利益です – scaisEdge

+0

備考:私の最終的なアプリケーションでは、 "John-Boy"という文字列が "t"と "A"の両方で計算された名前 'substring_index(substring_index(name、 ''、1)、 ' - '、1) 「John Ross」は「John」のように扱われます。正しく動作させるためには、 'count(gender)= 1'条件を' max(gender)= min(gender) 'に置き換える必要がありました。 –

1

Scaisの提供によるわずかな歪みで、テーブル全体の確率が高いことに基づいて適用します。明らかに小さなサンプルしか表示されていません。私は男性と女性として対応するカウントでファイルにあるすべての名前を取得しようとします。その結果は欠落している人に適用されるべきです。例として、あなたのテーブルに「ジャック」を男性に85回、女性に2回(私は実際ジャッキーに行った女性を知っていました)、男性としての「ジャック」が適用されます。

select 
     p.name, 
     sum(case when p2.gender = 'male' then 1 else 0 end) as maleCount, 
     sum(case when p2.gender = 'female' then 1 else 0 end) as femaleCount 
    from 
     people p 
     join people p2 
      on p.name = p2.name 
      AND p2.gender IS NOT NULL 
    where 
     p.gender is null 
    group by 
     p.name 

は今、そうでない場合は、我々は皆を更新することになる、Scaisと同様の方法で相関の更新と基礎..としても、我々は唯一の既存の性別はNULLされた場合に更新することを使用します。

UPDATE people A 
    INNER JOIN (above query) t 
     on t.name = a.name 
    set a.gender = case when t.maleCount > t.femaleCount 
         then 'male' else 'female' end 
    where a.gender IS NULL