【问题标题】:SQL MAX join query returns multiple rowsSQL MAX 连接查询返回多行
【发布时间】:2018-07-17 08:22:34
【问题描述】:

我编写了一个小的选择查询,它是我用来从 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

非常感谢您的帮助

【问题讨论】:

  • 请在您的问题中包含示例数据、表格定义和预期输出
  • 如果你只想要一行,所有分组的列都需要有一个精确的值。在您的情况下,isn.direction 有 2 个值。因此,您得到 2 行,因为 id1 和方向 1 的值与 id1 和方向 2 不同。如果您想每个 ...id_inventory 只返回一行,则必须仅按此分组并选择 max(isn.direction)
  • @MKhalidJunaid 抱歉回复晚了,我的办公桌上还有一些其他项目要完成。我已经提供了一些额外的信息,我希望它有助于找到解决方案。
  • @Chrᴉz 我理解你的建议。现在我可以看到问题所在。但我仍然无法解决它。我不能输入 max(isn.direction),因为我想检索数据,库存的最后一个问题说明的方向是什么。使用 MAX 我只得到那些带有 '2' 的。

标签: postgresql join max


【解决方案1】:

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

在这种情况下,每个inventory_id_inventory 的顺序似乎是升序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

partition by inventory_id_inventory 表示我们希望按inventory_id_inventory 对每个分区进行单独的排名。 order by issue_note_id_issue_notes desc 将为 最大 ID 返回 1,从而更容易过滤“最新”条目。

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

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);

结果将是:

|id |inventory_id_inventory |issue_note_id_issue_notes  |direction  |rn
|4  |12                     |4                          |1          |1
|6  |123                    |5                          |2          |1
|7  |35                     |6                          |1          |1

SQL 小提琴here

【讨论】:

  • 看来你说到点子上了。谢谢你。这按预期工作。
【解决方案2】:

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

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

【讨论】:

  • 抱歉回复晚了。这对我不起作用,因为它给我带来了更多重复的记录。请参阅主要帖子,因为我对其进行了编辑以提供更多详细信息。也许有帮助。
  • @Smok 请添加您期望从查询中获得的输出数据 - 这会有所帮助
  • 我已经编辑了我的主要帖子。如果我没有犯任何错误(在手动创建表中),它应该适合我的需要。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2017-06-02
  • 1970-01-01
  • 2011-01-17
  • 1970-01-01
  • 2010-10-27
  • 2022-01-23
  • 1970-01-01
  • 2014-11-19
相关资源
最近更新 更多