如何只获取有限数量的连接结果?

时间:2018-05-08 06:46:03

标签: sql sqlite join

我们假设,我有以下表格:

项目

  • id INT
  • 名称VARCHAR
  • owner_id INT

版本

  • id INT
  • project_id INT
  • tag VARCHAR
  • created_at DATETIME

所有者

  • ...(现在无关紧要)

我想检索一组项目,我想只加入每个项目的最新版本。 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。

我想知道,这个问题是否有一个“众所周知的”解决方案,我不知道?

1 个答案:

答案 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