質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Apex

Apexは、Salesforce上で動作するアプリケーション作成をサポートするアプリケーション開発プラットフォーム。プログラミング言語であるApexコードと、独自のApex WebサービスAPIなどで構成されています。

Q&A

解決済

1回答

3114閲覧

データ取得ロジック周りを簡潔に書く方法

退会済みユーザー

退会済みユーザー

総合スコア0

Apex

Apexは、Salesforce上で動作するアプリケーション作成をサポートするアプリケーション開発プラットフォーム。プログラミング言語であるApexコードと、独自のApex WebサービスAPIなどで構成されています。

0グッド

0クリップ

投稿2017/03/31 03:53

編集2017/03/31 06:14

変更履歴テーブルからデータを取得して表示するプログラムを書き、動作上は正常動作していますが、
より簡潔に書く方法があればご指導いただければ幸いです。

言語はsalesforceのapexというものになりますが、書き方はjavaと似ています。

早速ですが、データ構造から説明させていただきます。

変更履歴テーブルに以下のようなデータが入っている状態です。

作成日時項目名新しい値実行者
2017-03-31T02:35:41.000Zcontact_id003N0000010thphIAA横浜 太郎
2017-03-31T02:35:41.000Zdownload_datetime2017-03-31T02:35:41.000Z横浜 太郎
2017-03-31T02:35:41.000Zcontact_id横浜 太郎横浜 太郎
2017-03-31T02:36:41.000Zdownload_datetime003N0000010rrpHIAQ新宿 太郎
2017-03-31T02:36:41.000Zdownload_datetime2017-03-31T02:36:41.000Z新宿 太郎
2017-03-31T02:36:41.000Zcontact_id新宿 太郎新宿 太郎
2017-03-31T03:02:11.000Zdownload_datetime2017-03-31T03:02:11.000Z新宿 太郎

上記データを、プログラム通して、最終アウトプットしたものは以下です。

ダウンロード日時ダウンロード実行者
2017/03/31 11:35横浜太郎
2017/03/31 11:36新宿太郎
2017/03/31 12:02新宿太郎

変更履歴テーブルのデータは、以下の操作をしたときのデータになります。

1.横浜太郎というユーザがダウンロードを実行。
→上記の表のデータ1行目〜データ3行目が記憶されます。

2.新宿太郎というユーザがダウンロード実行
→上記の表のデータ4行目〜データ6行目が記憶されます。

3.新宿太郎というユーザが再度ダウンロード実行
→上記の表のデータ7行目が記憶されます。
(※contact_idが前回と同じ新宿太郎のため、8行目がつくられません)

また、データがたまる仕様、およびデータの抽出で、以下の制約があります。

  1. 項目名列のcontact_idにおいて、1行目と3行目や4行目と6行目のように
    IDと名称が残るものの、IDは最終的なアウトプットには必要ないので、プログラム上で除外しています。

  2. 項目名列のcontact_idにおいて、前回と同じであれば、レコードは作られません。

  3. 新しい値列はsql(soql)のwhere条件指定できません。

プログラムは以下です。

apex

1 // 処理実行プログラムです 2 public List<History> histories {get; set;} // ゲッターセッターの機能を持ちます Historyクラスはデータ保持クラスで構造は画面下に記載しました。 3 histories = new List<History>(); // アウトプットデータの初期化 4 History h = new History(); // soqlで取得したデータ(縦持ち)を、横持ちに変換と保持するクラス 5 String prevData2; // ダウンロード実行者が新旧で変化が無い場合はレコードが作成されないので旧のダウンロード実行者を保持して新にアサイン 6 Boolean notAdd = false; // NewValueがIdの場合は無視する=>true 7 Integer i = 0; 8 for (a_history hist: [ 9 SELECT 10 Field, 11 NewValue 12 FROM 13 a_history 14 WHERE 15 Field in ('download_datetime', 'contact_id') 16 ORDER BY 17 CreatedDate, Field, NewValue desc 18 ]) { 19 i++; 20 21 // 奇数のタイミングでhistoriesに追加とhistoryを生成 22 if (i >= 3 && math.mod(i, 2) == 1) { 23 if (notAdd) { 24 notAdd = false; 25 } else { 26 this.histories.add(h); 27 h = new History('', h.data2); 28 } 29 } 30 31 if ('download_datetime'.equals(hist.Field)) { 32 // 個人的に、特に以下の偶数・奇数判定が気持ち悪いです。必要でこうしたのですが、すでに説明できない。 33 if (math.mod(i, 2) == 1) { 34 h.data1 = Datetime.valueOf(hist.NewValue).format('yyyy/MM/dd HH:mm', 'JST'); 35 } else { 36 this.histories.add(h); 37 h = new History( 38 Datetime.valueOf(hist.NewValue).format('yyyy/MM/dd HH:mm', 'JST'), 39 h.data2 40 ); 41 i++; 42 } 43 } 44 45 if ('contact_id'.equals(hist.Field)) { 46 // contact_idを変更すると、Idと名称それぞれのレコードができている 47 // Idの場合は無視する(SOQLでNewValueで除外指定できない) 48 if (String.valueOf(hist.NewValue).indexOf('003') != -1) { 49 i++; 50 notAdd = true; 51 } else { 52 h.data2 = String.valueOf(hist.NewValue); 53 } 54 } 55 } 56 if (String.isNotBlank(h.data1)) { 57 this.histories.add(h); 58 } 59

apex

1 // データ保持クラスです 2 public class History { 3 public String data1 {get; set;} 4 public String data2 {get; set;} 5 public History() { 6 } 7 public History(String d1, String d2) { 8 this.data1 = d1; 9 this.data2 = d2; 10 } 11 }

何卒よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

変更履歴テーブルの作成日時が1回のダウンロード実行で一致してれば、
SQLの結果が以下のようになるかと思うので、

作成日時項目名新しい値
2017-03-31T02:35:41.000Zcontact_id003N0000010thphIAA
2017-03-31T02:35:41.000Zcontact_id横浜 太郎
2017-03-31T02:35:41.000Zdownload_datetime2017-03-31T02:35:41.000Z
2017-03-31T02:36:41.000Zcontact_id003N0000010rrpHIAQ
2017-03-31T02:36:41.000Zcontact_id新宿 太郎
2017-03-31T02:36:41.000Zdownload_datetime2017-03-31T02:36:41.000Z
2017-03-31T03:02:11.000Zdownload_datetime2017-03-31T03:02:11.000Z

上から順に処理していけば

  1. contact_idかつユーザ名だったらアウトプットを初期化して実行者を設定
  2. download_datetimeだったら日時を設定してリストに追加

for文の中だけ書くと

// ダウンロード実行者の設定・初期化 if ('contact_id'.equals(hist.Field) && String.valueOf(hist.NewValue).indexOf('003') != -1) { h = new History('', hist.NewValue); } // ダウンロード日時を設定してリスト化 if ('download_datetime'.equals(hist.Field)) { h.data1 = Datetime.valueOf(hist.NewValue).format('yyyy/MM/dd HH:mm', 'JST'); histories.add(h); }

みたいな感じで行けそうですがいかがでしょうか。
download_datetimeが複数回続くようだったらユーザ名は初期化されないので、問題ないかと思います。

投稿2017/03/31 07:19

szk.

総合スコア1400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/03/31 08:13

ご回答ありがとうございます。 > 作成日時が1回のダウンロード実行で一致 はい、一致します。 おそらく以下については、 String.valueOf(hist.NewValue).indexOf('003') != -1 以下の意図かと思いますが、 String.valueOf(hist.NewValue).indexOf('003') == -1 この場合、アウトプットが、2017/03/31 11:35の実行者の欄が 空白になってしまいました。 だいぶシンプルになりましたが・・・
szk.

2017/03/31 08:29 編集

ご指摘通り > String.valueOf(hist.NewValue).indexOf('003') == -1 ですね、コピペしてそのままでした、すいません。。 SQLの実行結果が期待通りか確認できますか。 SFDCということなので、別のソートが勝手にかかってそうで。。。 以下みたいな感じの戻り値だと、アウトプットの1行目の実行者は空白になっちゃいますね。。。 ※2行目と3行目が逆 |作成日時|項目名|新しい値| ||| |2017-03-31T02:35:41.000Z|contact_id|003N0000010thphIAA| |2017-03-31T02:35:41.000Z|download_datetime|2017-03-31T02:35:41.000Z| |2017-03-31T02:35:41.000Z|contact_id|横浜 太郎| |2017-03-31T02:36:41.000Z|contact_id|003N0000010rrpHIAQ| |2017-03-31T02:36:41.000Z|contact_id|新宿 太郎| |2017-03-31T02:36:41.000Z|download_datetime|2017-03-31T02:36:41.000Z| |2017-03-31T03:02:11.000Z|download_datetime|2017-03-31T03:02:11.000Z|
退会済みユーザー

退会済みユーザー

2017/03/31 09:03 編集

早速のご回答ありがとうございます。 すみません。Field列に書いた値に誤記がありました。 contact_idですが、正しくは 「download_contact_id」 でした。 申し訳ございません。 また、sfdcのsoqlで不可解なことがあり、 ORDER BY CreatedDate, Field, NewValue desc の指定であれば、Field列(項目名列)の並びはa→zになるはずなのに、 以下のように降順になってしまう動作しております。 2017-03-31T02:35:41.000Z download_datetime 2017-03-31T02:35:41.000Z 横浜 太郎 2017-03-31T02:35:41.000Z download_contact_id 横浜 太郎 横浜 太郎 2017-03-31T02:35:41.000Z download_contact_id 003N0000010thphIAA 横浜 太郎 2017-03-31T02:36:41.000Z download_datetime 2017-03-31T02:36:41.000Z 新宿 太郎 2017-03-31T02:36:41.000Z download_contact_id 新宿 太郎 新宿 太郎 2017-03-31T02:36:41.000Z download_contact_id 003N0000010rrpHIAQ 新宿 太郎 2017-03-31T03:02:11.000Z download_datetime 2017-03-31T03:02:11.000Z 新宿 太郎 逆に、Field列にdescといれると、以下のようになります。 ORDER BY CreatedDate, Field desc, NewValue desc  2017-03-31T02:35:41.000Z download_contact_id 横浜 太郎 横浜 太郎 2017-03-31T02:35:41.000Z download_contact_id 003N0000010thphIAA 横浜 太郎 2017-03-31T02:35:41.000Z download_datetime 2017-03-31T02:35:41.000Z 横浜 太郎 2017-03-31T02:36:41.000Z download_contact_id 新宿 太郎 新宿 太郎 2017-03-31T02:36:41.000Z download_contact_id 003N0000010rrpHIAQ 新宿 太郎 2017-03-31T02:36:41.000Z download_datetime 2017-03-31T02:36:41.000Z 新宿 太郎 2017-03-31T03:02:11.000Z download_datetime 2017-03-31T03:02:11.000Z 新宿 太郎 現在、どのようにしたらよいか混乱しているのですが、 soqlの取得結果が重要な点はわかっております・・・^^;
退会済みユーザー

退会済みユーザー

2017/04/01 03:53

ありがとうございました。色々コード改変して解決しました^^;
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問