创建视图,选择与另一列相关的一列中的最大值

create view selecting the max in one column related with another column

我需要在 PostgreSQL 9.4 中为此创建一个视图 table:

CREATE TABLE DOCTOR (
    Doc_Number INTEGER,
    Name    VARCHAR(50) NOT NULL,
    Specialty   VARCHAR(50) NOT NULL,
    Address VARCHAR(50) NOT NULL,
    City    VARCHAR(30) NOT NULL,
    Phone   VARCHAR(10) NOT NULL,
    Salary  DECIMAL(8,2) NOT NULL,
    DNI     VARCHAR(10) NOT NULL,
    CONSTRAINT pk_Doctor PRIMARY KEY (Doc_Number)
  );

该视图将显示每个 specialty 最高 salary 的医生的排名,我试过这段代码,但它显示了每个专业的所有医生:

CREATE VIEW top_specialty_doctors 
AS (Select MAX(Salary), name, specialty from DOCTOR
    where specialty = 'family and community'
    or specialty = 'psychiatry'
    or specialty = 'Rheumatology'
    group by name, salary, specialty);

视图只显示每个专业薪水最高的医生,我该怎么办。

这是一个按薪水显示每个专业的最佳医生的查询:

with specialty_ranks as (
  select 
    Salary, name, specialty,
    rank() over (
      partition by specialty
      order by salary desc
    ) as rank
  from DOCTOR
      where specialty in ('family and community', 'psychiatry', 'Rheumatology')
)
select specialty, name, salary
from specialty_ranks
where rank = 1;

查询使用 CTE and the RANK() window function 来完成这项工作。如果您以前没有使用过它们,您可能想阅读它们的文档。

DISTINCT ON 是一种简单的 Postgres 特定技术,可让每个组获得 一个 获胜者。详情:

  • Select first row in each GROUP BY group?

CREATE VIEW top_specialty_doctors AS 
SELECT DISTINCT ON (specialty)
       salary, name, specialty
FROM   doctor
WHERE  specialty IN ('family and community', 'psychiatry', 'Rheumatology')
ORDER  BY specialty, salary DESC, doc_number  -- as tiebreaker

而且您 不需要 需要在 CREATE VIEW.

的查询周围加上括号

如果多个文档的薪水最高,则选择doc_number 最低的那个。

如果salary可以为NULL,使用DESC NULLS LAST:

  • PostgreSQL sort by datetime asc, null first?

对于大表和某些数据分布,其他查询技术更胜一筹:

  • Optimize GROUP BY query to retrieve latest record per user

不使用通用 Table 表达式或分析,您可以使用内联 view/virtual table:

Create View top_specialty_doctors as
    Select  m.MaxSalary, d.Name, d.Specialty
    From    Doctor  d
    Join( -- Expose largest salary of each specialty
        Select  Specialty, Max( Salary) as MaxSalary
        From    Doctor
        Group by Specialty
    ) as m
        on  m.Specialty = d.Specialty
        and m.MaxSalary = d.Salary
    Where specialty in( 'family and community', 'psychiatry', 'Rheumatology' );

使用 CTE 而不是内联视图使查询更具可读性并允许查询优化器产生更好的性能(通常)。它们真的很容易学。