SQL Server - 在单个查询中查找最大和最小记录

时间:2018-03-30 11:55:20

标签: sql sql-server

我有以下表格

CREATE TABLE Patient
(
patientID int,
firstName varchar(50) NOT NULL,
middleName varchar(50),
surName varchar(50) NOT NULL,
p_age int NOT NULL,
p_gender char(1),
p_address varchar(200),
p_contact_no int,
medicalHistory varchar(500),
allergies varchar(200),
CONSTRAINT PK_Patient PRIMARY KEY (patientID)
);

CREATE TABLE Appointment
(
appID int,
patientId int,
staffId int,
appDateTime DateTime,
CONSTRAINT PK_Appointment PRIMARY KEY (appID),
CONSTRAINT FK_Appointment_Patient FOREIGN KEY (patientId) REFERENCES Patient(patientID) ON DELETE CASCADE,
CONSTRAINT FK_Appointment_Staff FOREIGN KEY (staffId) REFERENCES Staff(staffID) ON DELETE CASCADE,
CONSTRAINT CHK_AppointmentDate CHECK (appDateTime>=GETDATE())
);

我想获得总体预约最多和最少的患者的记录

这是我到目前为止所拥有的。但是这会返回重复的记录。除此之外,查询还可以。

WITH s
     AS (SELECT p.patientId, p.firstName,
                Count(a.appId)              AS [Count],
                MAX(Count(a.appId)) OVER () AS [MaxMyGroup],
                MIN(Count(a.appId)) OVER () AS [MinMyGroup]
         FROM   Patient p INNER JOIN Appointment a ON p.patientID = a.patientId
         GROUP  BY p.patientId, p.firstName)
SELECT patientId AS ID,
       firstName AS 'First Name',
       V.[Count] AS 'Appointment Count',
       Agg AS 'MAX/MIN'
FROM   s
CROSS APPLY (VALUES ( 'Most', CASE WHEN [Count] = [MaxMyGroup] THEN [Count] END),
                     ('Least', CASE WHEN [Count] = [MinMyGroup] THEN [Count] END))
             V(Agg, [Count])
WHERE V.[Count] IS NOT NULL

这是我目前的输出。如果我可以消除重复,那就太好了。

1   Paul    1   Most
1   Paul    1   Least
2   Dwayne  1   Most
2   Dwayne  1   Least
3   Brock   1   Most
3   Brock   1   Least
4   Chris   1   Most
4   Chris   1   Least
5   Melanie 1   Most
5   Melanie 1   Least
6   Kate    1   Most
6   Kate    1   Least
7   James   1   Most
7   James   1   Least
8   Bill    1   Most
8   Bill    1   Least
9   James   1   Most
9   James   1   Least

1 个答案:

答案 0 :(得分:0)

我不明白你使用apply的原因。一个简单的case似乎就足够了:

with s as (
      select p.patientId, p.firstName,
             Count(*) as cnt,
             max(Count(*)) over () as maxcnt,
             min(Count(*)) over () AS mincnt
      from Patient p join
           Appointment a
           on p.patientID = a.patientId
      group by p.patientId, p.firstName
     )
select s.*,
       (case when cnt = maxcnt then 'Most'
             when cnt = mincnt then 'Least'
        end) as agg
from s
where cnt in (maxcnt, mincnt);