【问题标题】:How to fetch only a limited number of joined results?如何仅获取有限数量的连接结果?
【发布时间】:2018-05-08 06:46:02
【问题描述】:

假设,我有以下表格:

项目

  • id INT
  • 名称 VARCHAR
  • owner_id INT

版本

  • id INT
  • project_id INT
  • 标记 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字段降序排列的,我需要第一个结果,即每个项目的最新结果。

这就是为什么我需要某种“选择性限制”,它会考虑versions.project_id 字段,就像SELECT DISTINCT 查询一样,但是,我需要从表中返回几乎所有字段,不仅是versions.project_id。

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

【问题讨论】:

  • 我无法遵循您的逻辑,因为我不知道这些列来自哪些表。
  • @GordonLinoff 我已经为我的示例查询添加了列名。

标签: sql sqlite join


【解决方案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

【讨论】:

  • 感谢您的解决方案!回家后我会试验一下。到目前为止,它看起来很有趣。测试后我会接受你的解决方案。
  • 它做到了!谢谢!
猜你喜欢
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
  • 2019-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-13
  • 1970-01-01
相关资源
最近更新 更多