2

私はモデルを持っていてsubmission、それはhas_many submissionstate(そしてそれぞれ2つのテーブルsubmissions)を持っていsubmissionstatesます。

submissionstates外部キーsubmission_idと別のstate_id列(およびupdated_atid)があります

の状態が変化するたびsubmissionに、新しい状態の新しいエントリがsubmissionstatesテーブルに作成されます。

state_id= 0で、状態が送信の最新の状態であるエントリを表示したいと思います。

たとえば、asubmissionには2つの状態(A(state_id = 0)とB(state_id = 1))があり、BはAの後に追加されます。したがって、Aがあるにもかかわらず、この送信がページに表示されないようにします最新の状態(B)ではありません。

私が使用した:

@submissions = Submission.includes(:submissionstates).where("submissionstates.state_id = 0").all

ただし、結果にはstate_id、送信の最新の状態でなくても、=0のすべての状態が含まれます。

これを機能させるには、クエリで何を変更する必要がありますか?

4

2 に答える 2

1

これは実際にはあなたの質問に答えませんが、それはあなたの問題を解決します

あなたは言う

たとえば、提出物には2つの状態(A(state_id = 0)とB(state_id = 1))、Bがあります。

これは間違っています。状態は特異性を意味します。つまり、やかんは沸騰することも冷たくすることもできません。状態フラグを送信テーブルに移動することを検討してください。状態がいつ変更されたかを知る必要がある場合は、submissionstatesテーブルを保持しますが、これはまったく異なる目的で使用します。

これを行うことにより、あなたはそれから使用することができます

@submissions = Submission.where("state" = 0)

必要に応じて、各州のスコープを設定できます。

scope:state_0、where(:state => 0)これで

@submissions = Submission.state_0

これはアプローチよりもはるかにスケーラブルですsubmissionstatesテーブルを保持することで、created_atフィールドを使用して特定の送信の状態の変更の日付と時刻を一覧表示できますが、これは通常のライブ使用よりも監査の履歴になります

コメントに基づく更新

別のsubmissionstatesテーブルを使用すると、必要な監査証跡が得られるため問題ありませんが、現在の状態を送信テーブルに保持する必要があります。

状態が変化するたびに送信レコードを更新することは、パフォーマンスの面で達成するのに十分簡単です。特に、submissionstatesテーブルから現在の状態を判別しようとする場合に直面するパフォーマンスの問題と比較した場合は大した問題ではありません。

私はあなたが両方を必要としていると言っています。提出物テーブルの現在の状態を維持することに問題がある場合は、叫んでください。それに対処できるかどうかを確認します。

于 2013-03-05T23:13:36.890 に答える
1

データベース構造に問題があります!

リレーショナルデータベースに関しては、常に1つのことを覚えておく必要があります。それは、行の一般的または自動の順序付けがないことです。

つまり、クエリの出力の順序に依存することはできません。問題は次のとおりです。DBMSはクエリを最適化し、呼び出さない場合ORDER BY、行を返す順序が定義されていません。(常に同じ順序であるように見えても、DBMSをアップグレードするか、単に中国で米の袋が倒れたために変更される可能性があります)。それに頼らないでください!

したがって、論理的な解決策は1つだけsubmissionstateです。つまり、自動生成された主キーまたはタイムスタンプのいずれかである、テーブルの3番目の列です。作成の時間が必要ない場合は、主キーを使用してください。

次に、テーブルは次のようになります。

id | submission_id | state_id
-----------------------------
1  | 4             | 3
2  | 8             | 3
3  | 4             | 2
4  | 6             | 1
5  | 4             | 5
6  | 8             | 0

私があなたを正しく理解していれば、あなたはそれらの結果を望んでいます:

  • submission_id = 4あなたが受け取りたいものを探しているならstate_id = 5
  • submission_id = 8あなたが受け取りたいものを探しているならstate_id = 0
  • submission_id = 6あなたが受け取りたいものを探しているならstate_id = 1

右?


解決策:

したがって、idフィールドが指定されている場合、探しているクエリは次のとおりです。

SELECT submission_id, state_id
FROM submissionstates ss
JOIN (
  SELECT MAX(id) as id
  FROM submissionstates ss
  GROUP BY submission_id
) x
ON ss.id = x.id

現在のstate_id=0の行のみが必要な場合は、次のようにします。

SELECT submission_id, state_id
FROM submissionstates ss
JOIN (
  SELECT MAX(id) as id
  FROM submissionstates ss
  GROUP BY submission_id
) x
ON ss.id = x.id
WHERE state_id = 0

すでにcreated_at列がある場合は、id列の代わりにそれを使用します。

SELECT submission_id, state_id
FROM submissionstates ss
JOIN (
  SELECT MAX(created_at) as created_at
  FROM submissionstates ss
  GROUP BY submission_id
) x
ON ss.created_at = x.created_at
WHERE state_id = 0
于 2013-03-05T23:15:47.003 に答える