2016-09-22 82 views
0

我创建了一个有3列的视图:service_id,professional_id和avg(评级),这个视图工作正常。分组和分组功能?

CREATE VIEW nota_profissionais 
AS 
    SELECT 
     service_id, professional_id, avg(nota) AS nota_media 
    FROM 
     avaliacao, servico_executado, solicitacao 
    WHERE 
     avaliacao.service_id = servico_executado.id 
     AND servico_executado.id_solicitacao = solicitacao.id 
    GROUP BY 
     service_id, professional_id; 

现在,每个service_id返回(每种类型的服务),我需要证明它具有最佳的平均等级的专业。我试着这样做:

SELECT 
    service_id, professional_id, MAX(nota_media) AS nota_media 
FROM 
    nota_profissionais 
GROUP BY 
    service_id, professional_id; 

但它从视图返回同样的事情,显示出每service_id为每professional_id。我知道为什么发生这种情况,但不知道如何正确执行此查询。对不起,如果我不清楚,因为英语不是我的母语。

+3

今天提示:切换到现代,明确的'JOIN'语法!更容易编写(没有错误),更易于阅读,并且更容易转换为外连接(如果需要)。 – jarlh

回答

0

您可以用LATERAL子查询做到这一点:

SELECT * 
FROM 
    (SELECT DISTINCT service_id FROM nota_profissionais) t1, 
    LATERAL (SELECT professional_id, nota_media 
      FROM nota_profissionais 
      WHERE service_id=t1.service_id 
      ORDER BY nota_media DESC LIMIT 1) t2 

这会发现所有不同service_id S(第一子查询),然后为他们每个人,它会找到一个最好的专业(第二子查询,与LATERAL)。

如果您有大量数据,请确保您有(service_id, nota_media DESC)的索引。

+0

不要求横向连接必须“重新运行”FROM中每个项目的查询?看起来像这样会比窗口解决方案慢得多,但我没有一个DB来测试。非常可爱的技巧寿。 – Hogan

+0

感谢aswer,它做到了。我会查找横向连接的文档。 –

+0

@ S.Costa我忘记了一个条件,现在可以重试吗? – redneb

1

您可以使用窗口函数来做到这一点:

SELECT service_id, professional_id, nota_media, 
FROM (
    SELECT service_id, professional_id, nota_media, 
     ROW_NUMBER() OVER (PARTITION BY service_id ORDER BY nota_media DESC) as RN 
) x 
WHERE RN = 1 
+0

感谢您的帮助 –

0

我认为最好的办法是DISTINCT ON

SELECT DISTINCT ON (service_id) np.* 
FROM nota_profissionais np 
ORDER BY service_id, nota_media DESC; 

不仅是在查询长度最短,但DISTINCT ON往往具有更好的性能与其他方法相比。

0

如果有几个专业人士相同的最好的评价,你想所有的人,不仅是第一个随机:

select t.* 
from nota_profissionais t 
    join (
    select service_id, max(nota_media) as nota_media 
    from nota_profissionais 
    group by service_id) t1 
    on (t.service_id = t1.service_id and t.nota_media = t1.nota_media) 

其实同样的结果应该返回@ Hogan的答案,如果改变ROW_NUMBER()RANK()函数。