Sql 复杂的分组查询,查找不属于分组依据的ID
我在使用这个SQL查询时遇到了一些问题,首先是一些背景知识 表定义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
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