postgres通过保留前一顺序进行分组

eqoofvh9  于 2021-07-29  发布在  Java
关注(0)|答案(1)|浏览(289)

我的问题是:

SELECT foo_id, bar, timestamp, ROW_NUMBER() OVER (ORDER BY timestamp ASC)
FROM foo_table
WHERE (foo_id = '1' OR related_foo_id = '1')
AND foo_body -> 'type' = 'My_foo_type';

我明白了:

╔═════════╦══════════╦══════════════╦══════════════╦
║ foo_id  ║    bar   ║  timestamp   ║  row_number  ║
╠═════════╬══════════╬══════════════╬══════════════╬
║  1      ║     1    ║      10      ║       1      ║
║  1      ║     1    ║      11      ║       2      ║
║  2      ║     1    ║      15      ║       3      ║
║  1      ║     2    ║      25      ║       4      ║
║  1      ║     2    ║      26      ║       5      ║
╚═════════╩══════════╩══════════════╩══════════════╩

我想通过'foo\u id'和'bar'值进行分组,得到如下结果:

╔═════════╦══════════╦══════════════╦══════════════╦
║ foo_id  ║    bar   ║  timestamp   ║  row_number  ║
╠═════════╬══════════╬══════════════╬══════════════╬
║  1      ║     1    ║      10      ║       1      ║
║  2      ║     1    ║      15      ║       2      ║
║  1      ║     2    ║      25      ║       3      ║
╚═════════╩══════════╩══════════════╩══════════════╩

按foo\u id和bar分组我必须去掉timestamp列,但我需要按它排序。我真的不在乎第一行还是第二行的结果总是唯一的。
我试着对结果进行排序和分组:

SELECT A.foo_id, A.bar, ROW_NUMBER() OVER ()
FROM (
  SELECT foo_id, bar FROM foo_table
  WHERE (foo_id = '1' OR related_foo_id = '1')
  AND foo_body -> 'type' = 'My_foo_type';
  ORDER BY timestamp ASC) A
GROUP BY foo_id, bar;

但它不尊重秩序:

╔═════════╦══════════╦══════════════╦══════════════╦
║ foo_id  ║    bar   ║  timestamp   ║  row_number  ║
╠═════════╬══════════╬══════════════╬══════════════╬
║  1      ║     1    ║      10      ║       1      ║
║  1      ║     2    ║      25      ║       2      ║
║  2      ║     1    ║      15      ║       3      ║
╚═════════╩══════════╩══════════════╩══════════════╩

在其他问题的答案后面,我也尝试了不同的连接,但我没有找到正确的连接。我第一次选择的结果总是一样的。
有没有一种方法可以在不影响性能的情况下得到我想要的?谢谢您

xpcnnkqh

xpcnnkqh1#

我想你想要 distinct on :

SELECT DISTINCT ON (foo_id, bar) foo_id, bar, timestamp, ROW_NUMBER() OVER (ORDER BY timestamp ASC)
FROM foo_table
WHERE (foo_id = 1 OR related_foo_id = 1) AND
      foo_body -> 'type' = 'My_foo_type'
ORDER BY foo_id, bar, timestamp asc;

这将返回一行 foo_id / bar 组合——时间戳最小的组合。这是基于 order by 以及 distinct on 条款。 DISTINCT ON 是一个postgres扩展,非常方便,是执行此类查询的最有效方法。

相关问题