4

現在のユーザーと他のユーザーとの間の「会話」で、それぞれが最新のメッセージのリストが必要です。

同じ質問がこの質問で説明されています

私がこれまでに持っているコードは次のとおりです。

t1 = Arel::Table.new(:messages, :as => 't1')
t2 = Arel::Table.new(:messages, :as => 't2')

convs1 = t1.
          project(
                  t1[:receiver_user_id].as('other_user_id'), 
                  t1[:receiver_user_id].as('receiver_user_id'), 
                  t1[:sender_user_id].as('sender_user_id'), 
                  t1[:created_at].as('created_at')
                 ).
          where(t1[:sender_user_id].eq(user.id))

convs2 = t2.project(
                  t2[:sender_user_id].as('other_user_id'), 
                  t2[:receiver_user_id].as('receiver_user_id'), 
                  t2[:sender_user_id].as('sender_user_id'), 
                  t2[:created_at].as('created_at')
                 ).
          where(t2[:receiver_user_id].eq(user.id))

conv = convs1.union(convs2)

まず、エラーが発生します。

ActiveRecord::StatementInvalid: Mysql2::Error: You have an error in your SQL syntax; check \
  the manual that corresponds to your MySQL server version for the right syntax to use near \
  'UNION SELECT `t2`...

これは、以下で生成されるSQLで「UNION」を「UNIONALL」に手動で置き換える場合に機能します。上記のコードのconv.to_sqlは、次のように生成します。

SELECT `t1`.`receiver_user_id` AS other_user_id, 
       `t1`.`receiver_user_id` AS receiver_user_id, `
        t1`.`sender_user_id` AS sender_user_id, 
       `t1`.`created_at` AS created_at 
  FROM `messages` `t1` 
 WHERE `t1`.`sender_user_id` = 50 
UNION 
SELECT `t2`.`sender_user_id` AS other_user_id, 
       `t2`.`receiver_user_id` AS receiver_user_id, 
       `t2`.`sender_user_id` AS sender_user_id, 
       `t2`.`created_at` AS created_at 
  FROM `messages` `t2` 
 WHERE `t2`.`receiver_user_id` = 50

MySQLUNIONエラーが発生する理由。それはアレルバグですか?第二に、クエリを完了するための助けをいただければ幸いです。

更新: Arel :: Nodes::Union.newの使用は機能します

4

4 に答える 4

3

これはおそらくmysqlの障害であると思います。これは、mySQLエラーテキストです。ここでは同様のことが説明されていますが、正確にはこの問題ではありません。

別のSQLサーバーに移行して、もう一度確認するか、union all機能する場合は次を使用してください。

conv = convs1.union(convs2, :all)

ドキュメントに基づいています。

于 2012-08-17T15:35:21.973 に答える
0

私は同様の問題を抱えていて、次のように解決しました:

  def last_messages
    Message.find_by_sql("
          SELECT  messages.*,
                  (IF(recipient_id = #{id}, 0,1)) as outlast,
                  users.avatar_name,
                  users.name 
          FROM messages 
          INNER JOIN users 
              ON users.id=(IF(recipient_id = #{id}, sender_id,recipient_id))
          WHERE messages.id IN 
              ( SELECT max(id)
                FROM messages
                WHERE recipient_id = #{id} OR sender_id = #{id}
                GROUP BY (IF(recipient_id = #{id}, sender_id, recipient_id))
              )
          ORDER BY messages.id DESC")
  end
于 2013-02-25T20:27:40.503 に答える
0

問題は、実際にはSQLの括弧です。私が実行すると動作します:

Message.find_by_sql conv.to_sql.delete('()')

先頭の「(」と末尾の「)」を削除します

奇妙な..クエリを完了するためにこれをチェーンする方法がわかりません。(Arel :: Nodes :: Unionにはグループメソッドがありません)。これはRails3.1.4です

于 2012-08-21T09:29:14.093 に答える
0

これは私が最後に代わりに使用したコードです

all_msgs = Message.where("messages.sender_user_id = ? OR messages.receiver_user_id = ?",
                                     user.id, user.id)

msg_ids = all_msgs.select("sender_user_id, receiver_user_id, max(id) as max_id")
.group(:sender_user_id, :receiver_user_id).map { |m| m.max_id }

all_msgs = all_msgs.where(:id => msg_ids)
于 2013-04-23T14:55:17.110 に答える