SQL 在第一个 table 中查询检查列或在第二个 table 中查找行
SQL query checking columns in first table or looking up rows in second table
所以我有以下情况:
我有一个 post 模型,它总是有 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
我想知道我是否可以编写一个查询来获取 posts 并满足以下条件:
1) post 有未经审核的参数,其中第一个按 ID 排序(不是 updated_at)属于 id = 5
的用户(例如)
------ 或 ------
2) post status = 1 and published = true
PS.: 我正在使用 PostgreSQL。
翻译成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
的详细信息:
- Select first row in each GROUP BY group?
为什么 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
,post 未通过条件 1)
将立即从选择中删除,并且永远不会有第二次机会。我添加了多余的括号(operator precedence 可以在没有括号的情况下为我们工作)和一个换行符以指出这是 "the other way in":
(a.status = 1 and a.published)
当然,我们现在必须添加条件1)
的检查:
a.post_id IS NOT NULL
这可以在不复制行的情况下工作,因为子查询 returns 每个 post(而不是更多)恰好 1 或 0 行。
这是一种解决方法。对于每个 post (2 - 4) 只有少数属性和大量合格属性来说应该是一个很好的选择。根据您的实际数据分布,可能还有其他更快的查询技术:
- Optimize GROUP BY query to retrieve latest record per user
所以我有以下情况:
我有一个 post 模型,它总是有 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
我想知道我是否可以编写一个查询来获取 posts 并满足以下条件:
1) post 有未经审核的参数,其中第一个按 ID 排序(不是 updated_at)属于 id = 5
的用户(例如)
------ 或 ------
2) post status = 1 and published = true
PS.: 我正在使用 PostgreSQL。
翻译成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
的详细信息:
- Select first row in each GROUP BY group?
为什么 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
,post 未通过条件 1)
将立即从选择中删除,并且永远不会有第二次机会。我添加了多余的括号(operator precedence 可以在没有括号的情况下为我们工作)和一个换行符以指出这是 "the other way in":
(a.status = 1 and a.published)
当然,我们现在必须添加条件1)
的检查:
a.post_id IS NOT NULL
这可以在不复制行的情况下工作,因为子查询 returns 每个 post(而不是更多)恰好 1 或 0 行。
这是一种解决方法。对于每个 post (2 - 4) 只有少数属性和大量合格属性来说应该是一个很好的选择。根据您的实际数据分布,可能还有其他更快的查询技术:
- Optimize GROUP BY query to retrieve latest record per user