SQL 查询以根据 table 关系获取最后一条记录

SQL query to get last record based on table relation

我有 3 tables boxes, stones and papers;每个盒子都通过一块石头与一张纸相关,所以我的目标是为每张纸获取最后一个盒子(盒子可以共享纸张)。已尝试使用 ActiveRecord 方式进入 rails 但无法在 uuid 库中使用聚合函数,因此这不起作用:

Box.joins(:stone).group('stone.paper_id').maximum(:id).values

自从缺少石头 table 以来,我一直在努力寻求一个纯粹的 SQL 声明,我有以下内容:

select distinct on (papers.id) boxes.created_at, boxes.id 
from papers 
left join boxes on paper.id = boxes.id 
order by paper.id, boxes.created_at DESC;

所有 3 个 table 主键都是 uuid 以及与查询无关的其他列,因为我只想 return 每篇论文的最后一个框的 uuid。

table:boxes
+--------------------------------------+-----------------+-----------+---------------------------------+--------------------------------------+
|                  id                  |      email      | delivered |           created_at            |               stone_id               |
+--------------------------------------+-----------------+-----------+---------------------------------+--------------------------------------+
| 61a341b0-a147-4534-9368-fdbc7b61fc0c | test@test.com   | true      | Fri, 04 Mar 2022 00:19:31 +0000 | 7fda6668-e9b2-45b3-957a-fbdbcd833cd0 |
| c20f4b61-8606-4aa7-870a-29b9df9d9492 | test2@test.com  | true      | Thu, 24 Feb 2022 11:42:01 +0000 | cdb35b8a-b553-4095-8b14-e855ebdf5044 |
| 9202384f-1895-4f94-9972-3ef837655aae | test3@test.com  | false     | Thu, 10 Mar 2022 00:59:54 +0000 | bbd5dcbc-b38d-4751-aaac-2b3dd83c5545 |
+--------------------------------------+-----------------+-----------+---------------------------------+--------------------------------------+

table:stones
+--------------------------------------+--------+------+---------------------------------+--------------------------------------+
|                  id                  | status | code |           created_at            |               paper_id               |
+--------------------------------------+--------+------+---------------------------------+--------------------------------------+
| 7fda6668-e9b2-45b3-957a-fbdbcd833cd0 |      1 |    3 | Sun, 06 Mar 2022 12:58:56 +0000 | a0acba15-e321-4f9f-996f-a6c16e56300d |
| cdb35b8a-b553-4095-8b14-e855ebdf5044 |      1 |    4 | Thu, 03 Mar 2022 19:57:14 +0000 | a0acba15-e321-4f9f-996f-a6c16e56300d |
| bbd5dcbc-b38d-4751-aaac-2b3dd83c5545 |      2 |    5 | Fri, 11 Mar 2022 11:50:08 +0000 | de936cf2-c158-4961-9ef4-60affc4ff87f |
+--------------------------------------+--------+------+---------------------------------+--------------------------------------+

table:papers
+--------------------------------------+------+---------------------------------+
|                  id                  | type |           created_at            |
+--------------------------------------+------+---------------------------------+
| a0acba15-e321-4f9f-996f-a6c16e56300d |    1 | Sat, 05 Mar 2022 05:59:00 +0000 |
| de936cf2-c158-4961-9ef4-60affc4ff87f |    5 | Thu, 03 Mar 2022 19:57:14 +0000 |
| 473a9dd4-3f38-49d0-8d1e-b5ab87e8ea92 |    4 | Sat, 12 Mar 2022 22:55:16 +0000 |
+--------------------------------------+------+---------------------------------+

box1 has a stone1 that relates to paper1
box2 has a stone2 that relates to paper1
box3 has a stone3 that relates to paper2

因此我想要 box1box3 uuid,因为它们是最新的盒子(按创建时间排序)对于每篇可用的论文,box2 被忽略,因为 paper1 与 box1 共享,而且它不是最新的。任何帮助都感激不尽!提前致谢!

result:most recent boxes ids
+--------------------------------------+
|                  id                  |
+--------------------------------------+
| 61a341b0-a147-4534-9368-fdbc7b61fc0c |
| 9202384f-1895-4f94-9972-3ef837655aae |
+--------------------------------------+

试试这个:

SELECT DISTINCT ON (p.id)
       b.id
  FROM boxes AS b
 INNER JOIN stones AS s
    ON s.id = b.stone_id
 INNER JOIN papers AS p
    ON p.id = s.paper_id
 ORDER BY p.id, b.created_at DESC

查看dbfiddle中的测试结果。

"SQL 根据 table 关系查询获取最后一条记录"

table 中没有记录,只是按任意顺序分组到页中的逻辑行。在 table 页面中没有像电子表格那样的默认或特定顺序,并且行作为堆放置在页面中。您一定很清楚,您将永远无法找到最后的“记录”!

在数据库中,您会发现,只有您要存储的内容。如果 you 想要找到 you 插入的最后一行,you 需要在插入语句。

我说 YOU,因为任何其他用户都可以同时使用相同的值执行相同的插入...这就是并发!

现在的问题是“你想要什么功能?

您可以执行此查询 (Result here)

with x as (
select row_number() over (partition by p.id order by b.created_at desc) as rn,b.id as id_box,p.id as id_paper
from boxes b join stones s on b.stone_id = s.id
join papers p on p.id = s.paper_id)
select x.id_box from x where rn = 1

cte 根据与 papers table 相关的 paper_id 找到最新的 id 。然后加入 box table.

尝试告诉我是否有帮助:

with cte as 
    (
      select s.id,
             s.paper_id,row_number() over(partition by paper_id order by created_at desc ) as rn
      from stones s
    ) select b.id
      from boxes b 
      inner join cte c on c.id=b.stone_id
      inner join papers p on c.paper_id=p.id
      where c.rn=1
      order by b.created_at desc;

Result:

id
9202384f-1895-4f94-9972-3ef837655aae
61a341b0-a147-4534-9368-fdbc7b61fc0c

Demo