0

我有一张objects桌子和votes桌子。我目前正在对它们进行分组并按最近的投票排序:

SELECT objects.id, objects.name, MAX(votes.created_at) AS mv 
       FROM "objects"
       INNER JOIN "votes" ON "votes"."object_id" = "objects"."id" 
       GROUP BY objects.id, objects.name 
       ORDER BY mv DESC

但是,这只返回有投票的对象。我搜索了 SO 并找到了有关如何包含不存在的结果的答案,但我希望同时包含那些存在和不存在的结果。

有没有办法将上述所有没有投票的对象都添加到末尾?

4

3 回答 3

1

INNER JOIN基本上返回在两个表上都有记录的结果。然后您应该使用LEFT JOIN它,因为它从左侧返回所有行,无论它在右表上是否有匹配记录。

   SELECT objects.id, objects.name, MAX(votes.created_at) AS mv 
   FROM "objects"
          LEFT JOIN "votes" ON "votes"."object_id" = "objects"."id" 
   GROUP BY objects.id, objects.name 
   ORDER BY mv DESC

JOIN 的可视化表示

希望这可以帮助。在此处输入图像描述

于 2012-09-10T22:39:07.863 回答
1

使用 a LEFT JOINNULL在找不到匹配行的地方填充值 - 正如您自己发现的那样

超级令人沮丧,因为它完美地工作,除了所有没有投票的条目都在开头!

现在,NULL通常排在最后。但与之相反,DESC它是第一位的。在 Postgres 中,您可以使用NULLS LAST显式排序NULL到末尾(从 8.3 版开始):


SELECT o.id, o.name, max(v.created_at) AS lastest_vote
FROM   objects o
LEFT   JOIN votes v ON v.object_id = o.id 
GROUP  BY o.id, o.name
ORDER  BY lastest_vote DESC NULLS LAST, o.name; -- name only as tiebreaker

如果objects.id是主键,您可以简化GROUP BY(在 Postgres 9.1 或更高版本中):

GROUP  BY o.id -- primary key covers all columns of this table
于 2012-09-11T03:03:58.843 回答
0

在您的陈述中使用"LEFT OUTER JOIN"而不是使用。"INNER JOIN"

干杯

于 2012-09-10T22:40:36.453 回答