SQL MAX联接查询返回多行

时间:2018-07-17 08:22:35

标签: postgresql join max

我写了一个小的选择查询,这是较大的查询的一部分,我使用它从PostgreSQL DB的几个表中检索带有附加属性的项目。

SELECT 
  isni.inventory_id_inventory,
  max(isni.issue_note_id_issue_notes) AS latest_issue_note,
  isn.direction
FROM issue_note_items isni
JOIN issue_notes isn ON isni.issue_note_id_issue_notes = isn.id
GROUP BY isni.inventory_id_inventory, isn.direction

我需要做的是使用inventory_id_inventory键为每个表获得一个记录,并具有最高的issue_note_id_issue_notes值。换句话说,我想查找最后一个问题便笺,其中包含每个单独的广告资源ID的方向。

我得到的是一两行-如果有两个不同的方向(此列中可能有两个小的int值)。似乎很容易,应该使用左连接进行修复,但是它可能无法正常工作,可能是因为GROUP BY子句。我应该怎么做才能使其按预期工作?

表格和示例数据:
issue_notes

ID  direction
1   1
2   2
3   2
4   1
5   2
6   1

issue_note_items

ID  inventory_id_inventory  issue_note_id_issue_notes
1   12                      1
2   123                     1
3   12                      2
4   12                      4
5   35                      4
6   123                     5
7   35                      6

预期输出:

ID  inventory_id_inventory  issue_note_id_issue_notes  direction
4   12                      4                          1
6   123                     5                          2
7   35                      6                          1

非常感谢您的帮助

2 个答案:

答案 0 :(得分:2)

关系数据库中的行没有顺序。除非有指定顺序,否则没有“最后”条目。

在这种情况下,顺序似乎是通过将每个inventory_id_inventory的{​​{1}}递增。在给定该顺序的情况下,可以使用inventory_id_inventory排名函数来计算每个联接结果的排名,例如:

ROW_NUMBER()

SELECT isni.id, isni.inventory_id_inventory, isni.issue_note_id_issue_notes, isn.direction, ROW_NUMBER() OVER(partition by inventory_id_inventory order by issue_note_id_issue_notes desc) as rn FROM issue_note_items isni JOIN issue_notes isn ON isni.issue_note_id_issue_notes = isn.issue_note_id 意味着我们希望每个库存分别按stock_id_inventory进行排名。 partition by inventory_id_inventory将为最大的 ID返回1,从而更易于过滤“最新”的条目。

不可能在order by issue_note_id_issue_notes desc子句中引用rn函数。这可以通过使用CTE来解决:

where

使用以下数据:

with notes as (
    SELECT 
      isni.id,
      isni.inventory_id_inventory,
      isni.issue_note_id_issue_notes,
      isn.direction,
      ROW_NUMBER() OVER( partition by inventory_id_inventory 
                         order by issue_note_id_issue_notes desc) as rn
    FROM issue_note_items isni
    JOIN issue_notes isn ON isni.issue_note_id_issue_notes = isn.issue_note_id      
)
select * 
from notes
where rn=1
order by issue_note_id_issue_notes

结果将是:

create table issue_notes (issue_note_id int,direction int);
create table issue_note_items (id int, inventory_id_inventory  int,issue_note_id_issue_notes int);

insert into issue_notes
values
(1,1),
(2,2),
(3,2),
(4,1),
(5,2),
(6,1);

insert into issue_note_items 
values
(1,12 ,1),
(2,123,1),
(3,12 ,2),
(4,12 ,4),
(5,35 ,4),
(6,123,5),
(7,35 ,6);

SQL小提琴here

答案 1 :(得分:0)

我在项目中写了一些东西,看起来可能是这样

SELECT 
  isni.inventory_id_inventory,
  isni.issue_note_id_issue_notes AS latest_issue_note,
  isn.direction
FROM issue_notes isn 
left join lateral (
  select 
    isni.inventory_id_inventory,
    isni.issue_note_id_issue_notes
  from issue_note_items isni
  where isni.issue_note_id_issue_notes = isn.issue_note_id
  order by isni.issue_note_id_issue_notes desc
  limit 1      
) as isni on true