SQL查询检查第一个表中的列或查找第二个表中的行

时间:2015-03-30 14:05:10

标签: sql ruby-on-rails postgresql greatest-n-per-group

所以我有以下情况:

我有一个帖子模型,总是有2个或4个参数

class Post < ActiveRecord::Base
  # has two columns, status and published (boolean)
  has_many :arguments
end

和参数模型

class Argument < ActiveRecord::Base
  # has moderated column (boolean) and text
  belongs_to :post
end

我想知道我是否可以编写查询来获取具有以下条件的帖子:

1)帖子有未经模仿的参数,其中第一个按id(not updated_at)排序,属于id = 5用户(例如)

------或------

2)帖子status = 1 and published = true

PS:我正在使用PostgreSQL。

1 个答案:

答案 0 :(得分:1)

转换为SQL:

SELECT p.*
FROM   posts p
LEFT   JOIN (
   SELECT DISTINCT ON (post_id)
          post_id, user_id
   FROM   arguments
   WHERE  moderated = FALSE
   ORDER  BY post_id, id
   ) a ON a.post_id = p.id AND a.user_id = 5
WHERE  a.post_id IS NOT NULL OR        -- condition 1
      (a.status = 1 and a.published);  -- condition 2

DISTINCT ON的详细信息:

为什么LEFT JOIN

如果只有条件1),我们可以简化:

SELECT p.*
FROM   posts p
JOIN  (
   SELECT DISTINCT ...
   ) a ON a.post_id = p.id AND a.user_id = 5;

但是您添加了替代(非附加)条件2)。如果我们使用普通[INNER] JOIN,那么未通过条件1)的帖子将立即从选择中删除,永远不会获得第二次机会。我添加了多余的括号(operator precedence对我们来说没有括号)和换行符指出这是&#34;另一种方式在&#34;:

(a.status = 1 and a.published)

当然,我们现在必须添加条件1)的检查:

a.post_id IS NOT NULL

这不会重复行,因为子查询每个帖子返回正好1或0 行(而不是更多)。

这是一种解决方法。应该是每个帖子(2 - 4)只有少数属性和一些非常重要的限定属性的绝佳选择。根据您的实际数据分布,可能还有其他更快的查询技术: