【问题标题】:Rails 3 - Complex active record query /w subqueriesRails 3 - 复杂的活动记录查询 /w 子查询
【发布时间】:2011-10-17 14:51:18
【问题描述】:

我有一个名为 actions 的简单历史记录表,类似于以下内容:

id | actionable_id | actionable_type | user_id
----------------------------------------------

表的 actionable_types 可以是“comment”、“vote”或“submission”,其中 actionable_id 与每个表的主键相关。同样,所有 cmets 和投票都属于提交。

此外,我有一个类似于以下内容的 friendships 表:

id | user_id | friend_id | user_id
----------------------------------

表的 user_id 属于拥有朋友的用户(friend_id 是朋友)。

如果您还没有猜到,任何时候用户对新提交的内容进行投票、投票或上传,它都会作为新的“操作”添加到历史记录表中。为单个用户的朋友获取所有操作既快速又简单,到目前为止效果很好。不过,这不是我的问题……

我想获取属于当前用户的非朋友组的所有 cmets 和投票。此外,仅当当前用户也对同一提交进行了投票或评论时,才会选择提交条目的 cmets 和投票。

因此,我需要进行以下两个查询,假设 current_user 是当前登录的用户。

查询 1 - 所有符合以下条件的投票类型操作:

  • 他们属于 current_user 的非好友
  • 他们不属于 current_user
  • current_user 至少有一个投票属于该提交(换句话说,如果一个投票属于这个集合,那么在该集合之外至少存在一个投票,其 vote.user_id = current_user.user_id)。

查询 2 - 所有符合以下条件的评论类型操作:

  • 他们属于 current_user 的非好友
  • 他们不属于 current_user
  • current_user 至少有一条评论属于该提交(换句话说,如果一条评论属于此集合,则集合之外至少存在一条comment.user_id = current_user.user_id 的评论)。

由于两个查询都访问同一个 Action 表,所以对我来说,最好有一个查询(尽管考虑到所需的 JOINS 数量,我觉得这不太可能)。

我这边的主要挂断是与检查非友谊相关的子查询和每个查询的最后一个条件(current_user 至少有一个......)。我将把我当前的查询代码库留给你,因为它甚至可能还不够接近。

感谢您的关注和帮助。

【问题讨论】:

    标签: ruby-on-rails activerecord join


    【解决方案1】:

    您想在那里进行相当复杂的查询。 这是我的建议(假设我正确理解了您的要求:

    SELECT a.* FROM actions a
    LEFT OUTER JOIN vote v
    ON v.id=a.actionable_id AND a.actionable_type='vote'
    LEFT OUTER JOIN comment c
    ON c.id=a.actionable_id AND a.actionable_type='comment'
    WHERE a.user_id<>current_user.id
    AND NOT EXISTS (
      SELECT 1 FROM friendships f
      WHERE f.user_id=current_user.id
      AND f.friend_id=a.user_id
    ) AND EXISTS (
      SELECT 1 FROM submission s
      LEFT OUTER JOIN vote v1
      ON v1.submission_id=s.id
      LEFT OUTER JOIN comment c1
      ON c1.submission_id=s.id
      WHERE (v1.id IS NOT NULL
      AND v1.submission_id=v.submission_id
      AND v1.id<>v.id
      AND v1.user_id=current_user.id) OR
      (c1.id IS NOT NULL
      AND c1.submission_id=c.submission_id
      AND c1.id<>c.id
      AND c1.user_ud=current_user.id)
    );
    

    所以我抓住所有行动并加入投票和反对行动的cmets。 然后我过滤掉所有与我当前用户拥有的相同 user_id 的操作。 确保该操作不是朋友的。 最后我得到提交并加入 current_users 投票和 cmets 反对他们,当提交的投票或评论存在时,与所选操作的提交相同,然后我找到了非朋友用户的操作你正在寻找。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多