Sql 复杂的分组查询,查找不属于分组依据的ID

Sql 复杂的分组查询,查找不属于分组依据的ID,sql,sql-server,sql-server-2005,group-by,Sql,Sql Server,Sql Server 2005,Group By,我在使用这个SQL查询时遇到了一些问题,首先是一些背景知识 表定义 create table [owner] ( [patientid] nvarchar(10) NOT NULL, [clientid] nvarchar(10) NOT NULL, [percentage] float NULL, [status] bit NOT NULL ) alter table [owner] ADD CONSTRAINT PK_OWNER PRIMARY KEY CLUSTERED

我在使用这个SQL查询时遇到了一些问题,首先是一些背景知识

表定义

create table [owner]
(
  [patientid] nvarchar(10) NOT NULL,
  [clientid] nvarchar(10) NOT NULL,
  [percentage] float NULL,
  [status] bit NOT NULL
)

alter table [owner] ADD CONSTRAINT PK_OWNER PRIMARY KEY CLUSTERED ([patientid],[clientid])
示例源数据

| PATIENTID | CLIENTID | PERCENTAGE | STATUS | ---------------------------------------------- | Pet1 | Owner1 | 100 | 1 | | Pet2 | Owner2 | 75 | 1 | | Pet2 | Owner3 | 25 | 1 | | Pet3 | Owner4 | 10 | 1 | | Pet3 | Owner5 | 90 | 1 | | Pet3 | Owner6 | 100 | 0 | | Pet4 | Owner7 | 50 | 1 | | Pet4 | Owner8 | 50 | 1 | 最近的一次是

SELECT f1.[patientid]
      ,f1.[clientid]
  FROM [OWNER] f1
inner join 
(
  select [patientid], max([percentage]) as [percentage]
  from [owner]
  where status = 1
  group by [patientid]
) f2 on f1.[patientid] = f2.[patientid] and f1.[percentage] = f2.[percentage]
where status = 1
然而,这给了我两条关于
Pet4
的记录

| PATIENTID | CLIENTID | ------------------------ | Pet1 | Owner1 | | Pet2 | Owner2 | | Pet3 | Owner5 | | Pet4 | Owner7 | | Pet4 | Owner8 |
您应该能够使用
row\u number()
通过按
patientid
应用分区并按百分比和clientid排序来获得结果:

select patientid, clientid
from
(
  select patientid, clientid, percentage, status,
    row_number() over(partition by patientid 
                      order by percentage desc, clientid) rn
  from owner
  where status = 1
) d
where rn = 1;

请参见您应该能够使用
行编号()
通过按
patientid
应用分区并按百分比和clientid排序来获得结果:

select patientid, clientid
from
(
  select patientid, clientid, percentage, status,
    row_number() over(partition by patientid 
                      order by percentage desc, clientid) rn
  from owner
  where status = 1
) d
where rn = 1;

请参见

我认为窗口功能,如@bluefeet的回答,使其更易于阅读。但是你已经接近了另一种语法。MIN()可以解析绑定行的字母顺序。(有些人认为MIN()只对数字起作用。)


我认为窗口功能,如@bluefeet的回答,使它更容易阅读。但是你已经接近了另一种语法。MIN()可以解析绑定行的字母顺序。(有些人认为MIN()只对数字起作用。)


一个相关的子查询也可以工作,尽管分区可以更好地扩展

declare @tmpOwner table (
    PatientID varchar(50),
    ClientID varchar(50),
    Percentage int,
    Status smallint
)

insert @tmpOwner (PatientID,ClientID,Percentage,Status)
SELECT 'Pet1','Owner1',100,1 UNION
SELECT 'Pet2','Owner2',75,1 UNION
SELECT 'Pet2','Owner3',25,1 UNION
SELECT 'Pet3','Owner4',10,1 UNION
SELECT 'Pet3','Owner5',90,1 UNION
SELECT 'Pet3','Owner6',100,0 UNION
SELECT 'Pet4','Owner7',50,1 UNION
SELECT 'Pet4','Owner8',50,1


select x.PatientID,
(SELECT top 1 ClientID 
 FROM @tmpOwner 
 where Percentage=max(x.Percentage) 
 and x.PatientID=PatientID
 order by ClientID) Win_Owner
from @tmpOwner x
where x.Status=1
group by PatientID

一个相关的子查询也可以工作,尽管分区可以更好地扩展

declare @tmpOwner table (
    PatientID varchar(50),
    ClientID varchar(50),
    Percentage int,
    Status smallint
)

insert @tmpOwner (PatientID,ClientID,Percentage,Status)
SELECT 'Pet1','Owner1',100,1 UNION
SELECT 'Pet2','Owner2',75,1 UNION
SELECT 'Pet2','Owner3',25,1 UNION
SELECT 'Pet3','Owner4',10,1 UNION
SELECT 'Pet3','Owner5',90,1 UNION
SELECT 'Pet3','Owner6',100,0 UNION
SELECT 'Pet4','Owner7',50,1 UNION
SELECT 'Pet4','Owner8',50,1


select x.PatientID,
(SELECT top 1 ClientID 
 FROM @tmpOwner 
 where Percentage=max(x.Percentage) 
 and x.PatientID=PatientID
 order by ClientID) Win_Owner
from @tmpOwner x
where x.Status=1
group by PatientID

啊,比我的解决方案好得多。啊,比我的解决方案好得多。蓝脚的解决方案更好:服务器只读取一次行。对于上述解决方案,服务器将读取两/三次行:
f1
f2
f3
。BlueFoots的解决方案更好:服务器只读取一次行。对于上述解决方案,服务器将读取行两/三次:
f1
f2
f3
declare @tmpOwner table (
    PatientID varchar(50),
    ClientID varchar(50),
    Percentage int,
    Status smallint
)

insert @tmpOwner (PatientID,ClientID,Percentage,Status)
SELECT 'Pet1','Owner1',100,1 UNION
SELECT 'Pet2','Owner2',75,1 UNION
SELECT 'Pet2','Owner3',25,1 UNION
SELECT 'Pet3','Owner4',10,1 UNION
SELECT 'Pet3','Owner5',90,1 UNION
SELECT 'Pet3','Owner6',100,0 UNION
SELECT 'Pet4','Owner7',50,1 UNION
SELECT 'Pet4','Owner8',50,1


select x.PatientID,
(SELECT top 1 ClientID 
 FROM @tmpOwner 
 where Percentage=max(x.Percentage) 
 and x.PatientID=PatientID
 order by ClientID) Win_Owner
from @tmpOwner x
where x.Status=1
group by PatientID