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

时间:2017-01-04 16:21:55

标签: sql postgresql greatest-n-per-group

我在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 ...

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

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

nome            | cognome       | NomeFacolta    

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

如何更改或集成我的查询才能执行此操作?

2 个答案:

答案 0 :(得分:0)

如果您不想显示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;

答案 1 :(得分:0)

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

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

将包含恰好与orelez的{​​{1}}相同id的任何行,而不仅仅是id

可以修复

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

但还有更多。只有子查询被限制为IE2.annoaccademico = '2009/2010'。外部查询没有相同的限制,因此只要annoaccademico匹配,它就会返回任何 orelez的行。你必须重复谓词。你真的想找到可能

orelez 的任何id匹配最大annoaccademico = '2009/2010'的所有行。

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

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值的可能拐角情况以及如何断开关系的详细说明和说明:

调试说明

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

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