0

ユーザーとステータスの2つのテーブルがあります

ステータステーブルには、user_id、status、occured_onがあります。ステータスは「削除済み」または「追加済み」のいずれかであり、occured_onはユーザーが削除または追加された日付です。

現在追加されているユーザーが必要です。つまり、最新のステータスレコードが「追加」されたすべての(個別の)ユーザーです。

Railsを使用していて、次のことを試しました。

User
  .joins(:statuses)
  .where('statuses.status = ?', 'added')
  .order('statuses.occured_on DESC')
  .uniq

これはSQLに変換されます:

SELECT DISTINCT users.* 
FROM users
INNER JOIN statuses
ON statuses.user_id = users.id 
WHERE statuses.status = 'added' 
ORDER BY statuses.occured_on DESC

それは私にエラーを与えます:

PG::Error: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list
   LINE 1: ...statuses.status = 'added') ORDER BY statuses.oc...

動作するRailsコードまたはストレートSQLのいずれかを知ってうれしいです。

また、可能であれば副選択はしたくないです。

4

2 に答える 2

1

次のデータベース スキーマの変更を検討してください。

ステータス テーブル:

StatusId
Status
UserId
ActiveFrom
ActiveTo

その後、次のような追加のチェックを追加できます。

CONSTRAINT chk_from_to CHECK (ActiveFrom <= ActiveTo)

次に、クエリは次のようになります。

   SELECT users.*
   FROM users 
   JOIN statuses ON UserId = users.user_id AND ActiveFrom < CURRENT_TIMESTAMP AND ActiveTo > CURRENT_TIMESTAMP
   WHERE statuses.Status = 'active'

このような構造では、ステータスを変更する方法を変更する必要があるかもしれませんが、私自身の経験から、この構造ははるかに柔軟で、クエリが簡単です。

于 2012-10-05T14:33:39.720 に答える
0
SELECT * FROM users INNER JOIN statuses ON users.id=statuses.user_id WHERE statuses.status='added' ORDER BY statuses.occured_on

明確にした後、スキーマがあなたの目標のためにうまく設計されているとは思いません。そのテーブルにステータス変更履歴を含める必要がある理由を明確にできますか?これに対する私の一般的なアプローチは、アクティブユーザーをprojects_usersというテーブルに含め、project_id、user_idを含めることです。それらが「削除」されたら、そのテーブルから削除する必要があります。アクションのログ(プロジェクトへのユーザーの追加と削除)は、別のテーブルに保存する必要があります。

あなたの現在のデザインを考えると、このクエリを書くために私が知っている良い方法はありません。エラーを修正した場合でも、これはMySQLでエラーなしで実行されます(これはまさにあなたが持っているものです)

SELECT DISTINCT `users`.* FROM `users`
INNER JOIN `projects_users`
ON `users`.`id`=`projects_users`.`user_id`
WHERE `status`='added'
ORDER BY `projects_users`.`occured_on` DESC

それでも正しい結果は得られません。ORDER BY句は、「追加」への最新の変更を取得するだけであり、より最近の「削除」アクションがないことを保証するものではありません。これを行うには、ユーザーごとに、最後に追加された各レコードの日付を最後に削除されたレコードの日付と比較する必要があります。

于 2012-10-05T14:00:19.917 に答える