1

我在使用这个 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])

示例源数据

| 患者 ID | 客户 ID | 百分比 | 状态 |
----------------------------------------------
| 宠物1 | 所有者1 | 100 | 1 |
| 宠物2 | 所有者2 | 75 | 1 |
| 宠物2 | 所有者3 | 25 | 1 |
| 宠物3 | 所有者4 | 10 | 1 |
| 宠物3 | 所有者5 | 90 | 1 |
| 宠物3 | 所有者6 | 100 | 0 |
| 宠物4 | 所有者7 | 50 | 1 |
| 宠物4 | 所有者8 | 50 | 1 |

我正在寻找的是我想要拥有最高百分比的宠物的主人,1如果出现平局,它应该按主人姓名的字母顺序排列。

所以这是我想看到的输出

| 患者 ID | 客户 ID |
----------------------
| 宠物1 | 所有者1 |
| 宠物2 | 所有者2 |
| 宠物3 | 所有者5 |
| 宠物4 | 所有者7 |

我得到的最接近的是

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

| 患者 ID | 客户 ID |
----------------------
| 宠物1 | 所有者1 |
| 宠物2 | 所有者2 |
| 宠物3 | 所有者5 |
| 宠物4 | 所有者7 |
| 宠物4 | 所有者8 |

处理这样的事情的正确方法是什么,所以我只得到一条记录,然后在领带上应用字母顺序来找到一条记录?

这是一个用于尝试任何答案的SQL Fiddle 工作区。


编辑:

我想出了一种方法来做到这一点,但对我来说它散发着代码气味,有没有更“正确”的方法来做到这一点?

select distinct f3.[patientid], (
  SELECT top 1 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 and f1.[patientid] = f3.[patientid]
  order by f1.[patientid], f1.[clientid]
)
from owner f3
4

3 回答 3

1

您应该能够row_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;

请参阅带有演示的 SQL Fiddle

于 2013-07-16T16:46:54.677 回答
0

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

SELECT f1.[patientid]
     , MIN(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]
GROUP BY f1.patientid
于 2013-07-16T17:02:58.120 回答
0

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

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
于 2013-07-16T19:24:23.840 回答