Postgres GROUP BY,然后排序

Postgres GROUP BY, then sort

我有一个数据库查询:

SELECT 
  Foo,
  Foo2,
  some_calc as Bar,
  some_other_calc as Bar2,
From
 FooBar
-- some inner joins for the calcs
GROUP BY FOO
ORDER BY Bar DESC, Bar2 DESC;

我想通过订单查询按数据库排序,然后将 FOO 组合在一起,以便第一个分组的块包含具有最大 Bar 的 FOOFOOs 的第二个分组块包含第二个最高的 Bar,等等

但这不起作用,因为 Postgres 不允许随机分组:

column "Bar" must appear in the GROUP BY clause or be used in an aggregate function.

我该如何解决这个问题?

示例数据和输出:

╔═════╦══════════╦════╦════╦
║ FO  ║ Bar      ║  Bar 2  ║
╠═════╬══════════╬═════════╬
║  6  ║     10   ║         ║
║  4  ║     110  ║         ║
║  3  ║     120  ║         ║
║  8  ║     140  ║         ║
║  3  ║     180  ║         ║
║  3  ║     190  ║         ║
╚═════╩══════════╩════╩════╩

输出:

╔═════╦══════════╦════╦════╦
║ FO  ║ Bar      ║  Bar 2  ║
╠═════╬══════════╬═════════╬
║  3  ║     190  ║         ║
║  3  ║     180  ║         ║
║  3  ║     120  ║         ║
║  8  ║     140  ║         ║
║  4  ║     110  ║         ║
║  6  ║     10   ║         ║
╚═════╩══════════╩════╩════╩

你只要order byGroup by 通过聚合减少(通常)行数。

您可以使用 window 函数完成此操作:

SELECT Foo, Bar, Bar2,
From FooBar
ORDER BY MAX(Bar) OVER (PARTITION BY Foo) DESC,
         Foo;

这不应该满足您的要求吗?

如果没有,如果您可以在查询中提供一些示例数据并显示您希望如何将其作为输出,将会有所帮助。

SELECT 
  Foo,
  MAX(some_calc) as Bar,
  MAX(some_other_calc) as Bar2,
From
 FooBar
##some inner joins for the calcs
GROUP BY FOO;
SELECT foo, <some calc> AS bar, bar2
FROM   foobar
ORDER  BY max(<some calc>) OVER (PARTITION BY foo) DESC NULLS LAST  -- can't refer to bar
        , bar DESC NULLS LAST  -- but you can here
        , foo DESC NULLS LAST;

bar 不必是列,可以是任何有效的表达式,甚至是聚合函数(与 GROUP BY 组合)——只是不是另一个 window 函数,它不能嵌套。示例:

  • PostgreSQL - Referencing another aggregate column in a window function

不能,但是,在window 函数内的同一查询级别上引用列别名(输出列名)。您必须再次拼出表达式,或将计算移动到子查询或 CTE。
可以 引用 ORDER BYGROUP BY 中的输出列名称,否则(但不能在 WHEREHAVING 子句中)。解释:

  • GROUP BY + CASE statement
  • PostgreSQL Where count condition

由于尚未定义,我们必须期待 NULL 值。通常您最后需要 NULL 值,因此按降序添加 NULLS LAST。参见:

  • Sort by column ASC, but NULL values first?

假设您首先想要更大的 foo,以防与 bar 相关。