如何获取一列中具有最大值的行?

How to get rows with the greatest value in one column?

我在 Postgres 中有这个查询:

SELECT DISTINCT P.nome, P.cognome, F.nomeFacolta, F.id, D.orelez
FROM Persona P, Docenza D, InsErogato IE, Facolta F
WHERE D.id_inserogato = IE.id
    AND IE.id_facolta = F.id
    AND D.id_persona = P.id
    AND D.orelez = ANY ( SELECT MAX(D2.orelez)
        FROM Facolta F2, Docenza D2, Inserogato IE2
        WHERE D2.id_inserogato = IE2.id
            AND IE2.id_facolta = F2.id
            AND IE2.annoaccademico = '2009/2010'
        GROUP BY F2.id)
ORDER BY D.orelez DESC;

结果如下:

nome            | cognome       | NomeFacolta    | id | orelez |

Francesco         Bortolan        Medicina         7    128000  <---
Giampaolo         Dalle Vedove    Economia         2    98000   <---
Mauro             Spera           Scienze          1    87000   <---
Alessandra        Salomoni        Economia         2    80000
Alessandro        Natucci         Economia         2    80000
Attilio           Boner           Medicina         7    80000
Mario Rosario     Buffelli        Lettere          8    76000   <---
Carlo             Capelli         Lettere          8    72000
etc ...

我想更改或整合我的查询以仅获取 id 的 MAX orelez 值(我用箭头指示了我想保留在结果中的元组)。我还希望我的查询只采用前三个属性,丢弃最后两个。

这是上述示例所需的输出:

nome            | cognome       | NomeFacolta    

Francesco         Bortolan        Medicina    
Giampaolo         Dalle Vedove    Economia    
Mauro             Spera           Scienze      
Mario Rosario     Buffelli        Lettere     
etc ...

如何更改或整合我的查询来执行此操作?

如果您不想显示 idorelez,请使用按 id 分组的子查询,然后显示所需的列。

SELECT R.nome, R.cognome, R.nomeFacolta
FROM (SELECT 
          F.id, P.nome, P.cognome, F.nomeFacolta, MAX(orelez) as orelez
      FROM 
          Persona P, 
          JOIN Docenza D ON D.id_persona = P.id, 
          JOIN InsErogato IE ON D.id_inserogato = IE.id, 
          JOIN Facolta F ON IE.id_facolta = F.id
      WHERE
          IE2.annoaccademico = '2009/2010'
      GROUP BY 
          F.id, P.nome, P.cognome, F.nomeFacolta) R
ORDER BY 
    R.orelez DESC;

的查询很可能不正确。谓词:

WHERE  D.orelez = ANY (SELECT MAX(D2.orelez) ...

将包括恰好与任何 id 的最大值相同 orelez 的任何行,而不仅仅是相同的 id.

可以修复:

 WHERE (F.id, D.orelez) = ANY (SELECT F2.id, MAX(D2.orelez) ...

但还有更多。只有子查询被限制为IE2.annoaccademico = '2009/2010'。外部查询没有相同的限制,所以它会 return 行 any annoaccademico,只要 orelez 匹配。您将不得不重复谓词。 可能你真的想找到:

对于任何 idannoaccademico = '2009/2010'.

匹配最大值 orelez 的所有行

但这似乎不太可能。假设你真的想找到:

每个 id 一行,最大 orelezannoaccademico = '2009/2010'

这可以用 DISTINCT ON 彻底简化:

SELECT DISTINCT ON (F.id)
       P.nome, P.cognome, F.nomeFacolta
FROM   Persona    P
JOIN   Docenza    D  ON D.id_persona = P.id
JOIN   InsErogato IE ON IE.id = D.id_inserogato
JOIN   Facolta    F  ON F.id = IE.id_facolta
WHERE  IE.annoaccademico = '2009/2010'
ORDER  BY F.id, D.orelez DESC;

关于可能的 NULL 值极端情况以及如何打破平局的详细解释和说明:

  • Select first row in each GROUP BY group?

调试说明

可能无法产生预期结果的典型原因:

  1. 有更多行具有相同的最大值。 D.orelez 中的值。 (你想 return 所有这些吗?那么你需要一个不同的查询。)
  2. 最大。 D.orelez 中的值不适用于 annoaccademico = '2009/2010'.
  3. 行可能会被联接删除,在 IEF 中找不到匹配项。
  4. D.orelez 中有 NULL 值 - 按照链接答案中的说明添加 NULLS LAST