Mysql Rails 5:如何按关联的模型属性对模型进行排序,并使其与众不同

Mysql Rails 5:如何按关联的模型属性对模型进行排序,并使其与众不同,mysql,ruby-on-rails,Mysql,Ruby On Rails,我在rails中有一个作用域,该作用域应该根据属性创建的最后一条聊天消息来排序一组对话。 事情是这样的: class Conversation < ApplicationRecord has_many :chat_messages, -> { order(created_at: :asc) }, dependent: :nullify do def last_from_user from_user.order("created_at ASC").l

我在rails中有一个作用域,该作用域应该根据属性创建的最后一条聊天消息来排序一组对话。 事情是这样的:

class Conversation < ApplicationRecord
    has_many :chat_messages, -> { order(created_at: :asc) }, dependent: :nullify do
      def last_from_user
        from_user.order("created_at ASC").last
      end

      def last_delivered_from_user
        from_user.order("delivered_at ASC").last
      end

      def last_from_agent
        from_agent.order("created_at ASC").last
      end
    end

    default_scope { joins(:chat_messages).order("chat_messages.created_at desc").distinct }
end
class Conversation < ApplicationRecord
    default_scope { joins(:chat_messages).order("chat_messages.created_at desc") }
end
    class ChatMessage < ApplicationRecord

      # Associations
      # ------------------------------------------------------------

      belongs_to :conversation
    end
SELECT conversations.*
FROM conversations
INNER JOIN chat_messages
  ON chat_messages.conversation_id = conversations.id
ORDER BY chat_messages.created_at desc
然而,我得到的是:

[1,2,3,4]
如果像这样删除distinct方法:

class Conversation < ApplicationRecord
    has_many :chat_messages, -> { order(created_at: :asc) }, dependent: :nullify do
      def last_from_user
        from_user.order("created_at ASC").last
      end

      def last_delivered_from_user
        from_user.order("delivered_at ASC").last
      end

      def last_from_agent
        from_agent.order("created_at ASC").last
      end
    end

    default_scope { joins(:chat_messages).order("chat_messages.created_at desc").distinct }
end
class Conversation < ApplicationRecord
    default_scope { joins(:chat_messages).order("chat_messages.created_at desc") }
end
    class ChatMessage < ApplicationRecord

      # Associations
      # ------------------------------------------------------------

      belongs_to :conversation
    end
SELECT conversations.*
FROM conversations
INNER JOIN chat_messages
  ON chat_messages.conversation_id = conversations.id
ORDER BY chat_messages.created_at desc
课堂对话
对话顺序良好,但会重复: [4,1,2,3,4]

我的聊天室消息模型如下所示:

class Conversation < ApplicationRecord
    has_many :chat_messages, -> { order(created_at: :asc) }, dependent: :nullify do
      def last_from_user
        from_user.order("created_at ASC").last
      end

      def last_delivered_from_user
        from_user.order("delivered_at ASC").last
      end

      def last_from_agent
        from_agent.order("created_at ASC").last
      end
    end

    default_scope { joins(:chat_messages).order("chat_messages.created_at desc").distinct }
end
class Conversation < ApplicationRecord
    default_scope { joins(:chat_messages).order("chat_messages.created_at desc") }
end
    class ChatMessage < ApplicationRecord

      # Associations
      # ------------------------------------------------------------

      belongs_to :conversation
    end
SELECT conversations.*
FROM conversations
INNER JOIN chat_messages
  ON chat_messages.conversation_id = conversations.id
ORDER BY chat_messages.created_at desc
class ChatMessage
我不能使用“unique”方法,因为这将使分页无法正常工作


但是,当一个对话有多条消息时,“distinct”方法会弄乱顺序。这个作用域按照对话创建的顺序返回对话,而不是按照我实际需要的顺序返回对话。

如果我们删除Rails,只需查看SQL语句,就会更清楚。您遇到的是一个典型的SQL问题,即试图获取一个基于联接按最大值或最小值排序的列表

您运行的查询如下所示:

class Conversation < ApplicationRecord
    has_many :chat_messages, -> { order(created_at: :asc) }, dependent: :nullify do
      def last_from_user
        from_user.order("created_at ASC").last
      end

      def last_delivered_from_user
        from_user.order("delivered_at ASC").last
      end

      def last_from_agent
        from_agent.order("created_at ASC").last
      end
    end

    default_scope { joins(:chat_messages).order("chat_messages.created_at desc").distinct }
end
class Conversation < ApplicationRecord
    default_scope { joins(:chat_messages).order("chat_messages.created_at desc") }
end
    class ChatMessage < ApplicationRecord

      # Associations
      # ------------------------------------------------------------

      belongs_to :conversation
    end
SELECT conversations.*
FROM conversations
INNER JOIN chat_messages
  ON chat_messages.conversation_id = conversations.id
ORDER BY chat_messages.created_at desc
每对对话和聊天信息都会返回一行。这就是为什么你有重复的

您不能将
distinct
与此一起使用

SELECT conversations.*
FROM conversations
INNER JOIN chat_messages
  ON chat_messages.conversation_id = conversations.id
ORDER BY chat_messages.created_at desc

ERROR 3065 (HY000): Expression #1 of ORDER BY clause is not in SELECT list,
references column 'test.chat_messages.created_at' which is not in SELECT list;
this is incompatible with DISTINCT
如果您使用
选择不同的对话。*,则在
中创建聊天信息。您回到了开始的位置

我不确定
.distinct
在做什么,但它可能会引发异常


相反,请使用
groupbyconversation.id
清除重复项。现在您已经有了分组查询,您可以
orderbymax(chat\u messages.created\u at)desc

select c.*
from conversations c
join chat_messages cm
  on cm.conversation_id = c.id
group by c.id
order by max(cm.created_at) desc
将此转换为Rails

Conversations
  .joins(:chat_messages)
  .group(:id)
  .order("max(chat_messages.created_at) desc")

如果我们删除Rails,只看SQL语句,就会更清楚。您遇到的是一个典型的SQL问题,即试图获取一个基于联接按最大值或最小值排序的列表

您运行的查询如下所示:

class Conversation < ApplicationRecord
    has_many :chat_messages, -> { order(created_at: :asc) }, dependent: :nullify do
      def last_from_user
        from_user.order("created_at ASC").last
      end

      def last_delivered_from_user
        from_user.order("delivered_at ASC").last
      end

      def last_from_agent
        from_agent.order("created_at ASC").last
      end
    end

    default_scope { joins(:chat_messages).order("chat_messages.created_at desc").distinct }
end
class Conversation < ApplicationRecord
    default_scope { joins(:chat_messages).order("chat_messages.created_at desc") }
end
    class ChatMessage < ApplicationRecord

      # Associations
      # ------------------------------------------------------------

      belongs_to :conversation
    end
SELECT conversations.*
FROM conversations
INNER JOIN chat_messages
  ON chat_messages.conversation_id = conversations.id
ORDER BY chat_messages.created_at desc
每对对话和聊天信息都会返回一行。这就是为什么你有重复的

您不能将
distinct
与此一起使用

SELECT conversations.*
FROM conversations
INNER JOIN chat_messages
  ON chat_messages.conversation_id = conversations.id
ORDER BY chat_messages.created_at desc

ERROR 3065 (HY000): Expression #1 of ORDER BY clause is not in SELECT list,
references column 'test.chat_messages.created_at' which is not in SELECT list;
this is incompatible with DISTINCT
如果您使用
选择不同的对话。*,则在
中创建聊天信息。您回到了开始的位置

我不确定
.distinct
在做什么,但它可能会引发异常


相反,请使用
groupbyconversation.id
清除重复项。现在您已经有了分组查询,您可以
orderbymax(chat\u messages.created\u at)desc

select c.*
from conversations c
join chat_messages cm
  on cm.conversation_id = c.id
group by c.id
order by max(cm.created_at) desc
将此转换为Rails

Conversations
  .joins(:chat_messages)
  .group(:id)
  .order("max(chat_messages.created_at) desc")

更大的问题是,为什么在该联接中会出现重复。如何定义与聊天信息的关系?“组织”如何适应这种情况?显示对话、聊天信息和任何其他相关模型的完整关系会有所帮助。这是一个简单的has\u many relation\u ship在聊天信息模型中我有一个属于参考,在对话模型中我有一个has\u many relationship你能将模型代码编辑到问题中以澄清吗,拜托?我刚刚更新了它。distinct方法破坏了scope应该返回按最后一条消息排序的对话的顺序,但它在添加distinct方法时按第一条消息排序。更大的问题是,为什么在该联接中会出现重复。如何定义与聊天信息的关系?“组织”如何适应这种情况?显示对话、聊天信息和任何其他相关模型的完整关系会有所帮助。这是一个简单的has\u many relation\u ship在聊天信息模型中我有一个属于参考,在对话模型中我有一个has\u many relationship你能将模型代码编辑到问题中以澄清吗,拜托?我刚刚更新了它,distinct方法破坏了scope返回对话的顺序,该顺序是按对话的最后一条消息排序的,但在添加distinct方法时,它会按第一条消息排序。