我们假设,我有以下表格:
项目
版本
所有者
我想检索一组项目,我想只加入每个项目的最新版本。 DISTINCT查询不适用于此目的,因为它限制了查询返回的列,但是我需要所有列。
这就是我提出的:
SELECT
projects.id, projects.name, projects.owner_id
FROM
projects
INNER JOIN
(SELECT versions.id, versions.project_id, versions.created_at, versions.tag FROM versions ORDER BY versions.created_at DESC LIMIT 1)
ON
projects.id = versions.project_id
WHERE
projects.owner_id = 1
更一般地说,我希望根据特定标准返回有限数量的联合结果。
但我想知道,有更好的解决方案吗?嵌套查询似乎不优雅,也可能效率不高。主要是我正在寻找一个SQLite兼容的解决方案,但如果有更好的方法用于其他SQL引擎,我也对它感兴趣,因为我已经在过去使用MySQL时遇到过这个问题。
更新:我想通过错误的解决方案进一步说明问题。最简单的方法是:
SELECT
projects.id, projects.name, versions.tag, versions.created_at
FROM
projects
INNER JOIN
versions
ON
projects.id = versions.project_id
WHERE
projects.owner_id = 1
ORDER BY
versions.created_at DESC;
这只是一个简单的JOIN结构。我们假设,它将给出以下数据集:
# id name tag created_at
1 1 project1 v2.3 2018-05-08 18:33:42
2 5 project5 v4.0 2018-05-08 11:19:07
3 3 project3 v1.8 2018-05-07 21:41:49
4 5 project5 v3.18 2018-05-07 07:00:26
5 8 project8 v3.12 2018-05-06 08:59:01
6 11 project11 v1.9 2018-05-05 14:27:31
7 5 project5 v3.17 2018-05-04 11:48:22
8 1 project1 v2.2 2018-05-04 05:11:46
9 2 project2 v5.5 2018-05-03 23:08:57
10 7 project7 v6.8 2018-05-03 12:17:33
解决方案是错误的,因为它也会返回不必要的行。我需要从这个数据集,行#1,2,3,5,6,9,10。 因为它是由versions.created_at字段按降序排序的,我需要第一个结果,即每个项目的最新结果。
这就是为什么我需要某种“选择性LIMIT”,它将versions.project_id字段考虑在内,就像SELECT DISTINCT查询一样,但是,我需要从表中返回几乎所有字段,不仅是versions.project_id。
我想知道,这个问题是否有一个“众所周知的”解决方案,我不知道?
答案 0 :(得分:1)
将ROW_NUMBER与项目id的分区和created_at的顺序一起使用,如下所示:
SELECT *
FROM
(SELECT
*, ROW_NUMBER() OVER(PARTITION BY project_id ORDER BY created_at DESC) AS row_no
FROM
projects
INNER JOIN
versions ON projects.id = versions.project_id) AS tbl
WHERE row_no = 1