0

私たちが使用しているサードパーティのシステムが原因で、データが重複しているテーブルがあります。モデルはEAVメソッドを使用しているため、これを「正しい」方法でフィルタリングする方法がないため、データをビューに集約しています-これはデータ収集の問題であることはわかっていますが、表示側で修正する方が簡単ですこのシステムを通過すると、既存のデータやフォームが壊れる可能性があります。2 つのフィールドのうちの 1 つまたは両方が入力されているかどうかを確認する必要がありますが、1 つだけを選択してください (そうしないと、名前が "John,John" の代わりに "John,John" のように 2 回表示されます)。関連する部分のコードは次のとおりです。

group_concat(
(
  case when (`s`.`fieldid` = 2) then `s`.`data` 
  else
    case when (`s`.`fieldid` = 35) then `s`.`data` 
    else NULL end 
  end
) separator ','),_utf8'') as first_name

fieldid 2 と fieldid 35 の両方が入力された場合、fieldid = 35 からの値ではなく、fieldid = 2 からの値が返されることを期待します。これは、元のケースが true の場合に Else 句が実行されないためです。しかし、それをつかんでいて、else 節の中でまだケースを実行していますか?

このコードを修正して、fieldid = 2 または fieldid = 35 のいずれかを取得するにはどうすればよいですか?ただし、両方をグロブ化して名前が重複しないようにすることはできますか?

編集

テーブル構造は次のとおりです。

table: subscribers_data
subscriberid (int)   fieldid (int)   data (text)    

これは EAV 構造を使用するため、サンプル レコードは次のようになります。

subscriberid          fieldid         data
1                     2               John
1                     3               Smith
1                     35              John
1                     36              Smith

fieldid 2 と 35 はカスタム フィールド「First Name」(別のテーブルで定義) であり、fieldid 3 と 36 は「Last Name」です。

私が使用している完全なビューは次のとおりです。

select `ls`.`subscriberid` AS `id`,
left(`l`.`name`,(locate(_utf8'_',`l`.`name`) - 1)) AS `user_id`,
ifnull(group_concat((
    case when (`s`.`fieldid` = 2) then `s`.`data` 
    when (`s`.`fieldid` = 35) then `s`.`data` 
    else NULL end) separator ','),_utf8'') AS `first_name`,
ifnull(group_concat((
    case when (`s`.`fieldid` = 3) then `s`.`data` 
    when (`s`.`fieldid` = 36) then `s`.`data` 
    else NULL end) separator ','),_utf8'') AS `last_name`,
ifnull(`ls`.`emailaddress`,_utf8'') AS `email_address`,
ifnull(group_concat((
    case when (`s`.`fieldid` = 81) then `s`.`data` 
    else NULL end) separator ','),_utf8'') AS `mobile_phone`,
ifnull(group_concat((
    case when (`s`.`fieldid` = 100) then `s`.`data` 
    else NULL end) separator ','),_utf8'') AS `sms_only` 
from ((`list_subscribers` `ls` 
join `lists` `l` on((`ls`.`listid` = `l`.`listid`))) 
left join `subscribers_data` `s` on((`ls`.`subscriberid` = `s`.`subscriberid`))) 
where (left(`l`.`name`,(locate(_utf8'_',`l`.`name`) - 1)) regexp _utf8'[[:digit:]]+') 
group by `ls`.`subscriberid`,`l`.`name`,`ls`.`emailaddress`

ビューは Ruby on Rails アプリケーションのモデルとして使用されているため、私はいくつかの創造的なハッキングを使用して、Rails が期待する「user_id」を偽造しています (数値 ID を使用して Lists テーブルのフィールドに list.name という名前を付けています)。新しいユーザーを追加すると、フロントエンド Rails アプリが生成するので、ビューを Rails コンベンション データベース テーブルのように見せるために、この番号だけを抽出しています)。

4

2 に答える 2

3

私は mysql の専門家ではありませんが、SQL サーバーのケース ステートメントでは、最初の「else」がなくても実行できます。

case
  when fieldid = 2 then data
  when fieldid = 35 then data
  else null
end

また、どちらの場合も同じ「データ」フィールドを返しているようです

于 2009-10-25T13:57:24.230 に答える
1

内部にgroup_concat()は、実行中のコンテキストを表示する方法がありません。したがって、1 つのグループに 2 つの行があり、1 つは でfieldid=2、2 番目は でfieldid=35、次のようになります。

  • 行を処理fieldid=2中 ...
    • s.fieldid = 2真です、戻りますs.data
  • 行を処理fieldid=35中 ...
    • s.fieldid = 2は false です。そのelse部分を試してください
    • s.fieldid = 35真です、戻りますs.data

これは、"John" が複数回返される理由を説明しています。これを修正する唯一の方法は、 の外で別のクエリを実行することですgroup_concat()

編集:

本当にこのようにしなければならない場合は、代わりに次のようなものを使用してください。

SELECT ...
   min(CASE WHEN s.fieldid IN (2,35) THEN s.data ELSE NULL END) AS first_name
...

group_concat(DISTINCT ...)の方法として、2 つの値が異なっていてはならない場合に行うこともできます (そうしないと、たとえば「John,Johny」となります)。ただし、first_name/last_name に 2 つの値があるのはなぜですか?

于 2009-10-25T14:03:22.513 に答える