2013-07-16 17 views
1

我有一點麻煩與此SQL查詢,第一一些背景複雜分組查詢,尋找ID不是該組的一部分BY

表定義

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 | 

我想要的是我想要擁有最高百分比的所有者,每個寵物的狀態爲1,如果平行,應該按照所有者的字母順序按字母順序排列,的名字。

因此,這裏的輸出I希望看到

 
| PATIENTID | CLIENTID | 
------------------------ 
|  Pet1 | Owner1 | 
|  Pet2 | Owner2 | 
|  Pet3 | Owner5 | 
|  Pet4 | Owner7 | 

我得到的最接近是

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 | 

什麼是處理這樣的事情的正確方法,所以我只能得到一個記錄,我申請的領帶字母順序找到一個記錄?

這裏是一個SQL Fiddle workspace嘗試任何答案。


編輯:

我想出辦法如何做到這一點,但對我來說惡臭碼味的,是有這樣做的更「正確」的方式?

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 
+0

bluefeet的解決方案是更好的:服務器將讀取行就一次。對於上述解決方案,服務器將讀取兩/三行:'f1','f2','f3'。 –

回答

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 with Demo

+1

啊,比我的解決方案好多了。 –

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 
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