2011-09-12 208 views
0

我試圖做的是從一個表,並在其中一個人的存在時的人員名單不止一次然後恢復包含排名最高的「代碼」他們的戰績的Oracle/SQL - 使用排序功能

代碼排序(從高到低):T,E,F

因此,對於給定的數據集

Person Code 
----------------  
Tom  F 
Paul E 
Mark F 
Paul T 
Mark E 
Chris T 
Chris E 

我會得到以下從我的查詢回來

Person Code 
---------------- 
Tom  F 
Paul T 
Mark E 
Chris T 

我假設這是將要使用的等級/分析功能,但我只是沒有足夠的熟悉與他們。

謝謝!

回答

0

最短和最高效和Oracle具體的解決辦法:

SQL> create table mytable(person,code) 
    2 as 
    3 select 'Tom', 'F' from dual union all 
    4 select 'Paul', 'E' from dual union all 
    5 select 'Mark', 'F' from dual union all 
    6 select 'Paul', 'T' from dual union all 
    7 select 'Mark', 'E' from dual union all 
    8 select 'Chris', 'T' from dual union all 
    9 select 'Chris', 'E' from dual 
10/

Table created. 

SQL> select person 
    2  , max(code) keep (dense_rank first order by decode(code,'T',1,'E',2,'F',3,4)) code 
    3 from mytable 
    4 group by person 
    5/

PERSO C 
----- - 
Chris T 
Mark E 
Paul T 
Tom F 

4 rows selected. 

問候,
羅布。

0

我不認爲RANK是你所需要的...

基本上,你的刪除看起來就像這樣:(僞查詢)

delete the rows from person 
where that row is not in (select the rows from person with the highest code) 

編輯

這個技巧也可以幫助你:

select person, code, decode(code, 'T', 1, 'E', 2, 'F', 3, 0) from mytable 
+0

刪除?我想他想查詢最高排名,而不是刪除數據。 –

+0

嗯..我解釋TRIM意味着擺脫...也許不是.. – Randy

+0

正確我不想刪除 - 只需要返回表中的每個人的結果。如果一個人列出的次數不止一次,而是返回「代碼」排名最高的記錄。我可以看到「修剪」可能會產生誤導。 – dscl

2

你可以使用該RANK功能排名數據

SQL> ed 
Wrote file afiedt.buf 

    1 with data as (
    2 select 'Tom' person, 'F' code from dual union all 
    3 select 'Paul', 'E' from dual union all 
    4 select 'Paul', 'T' from dual union all 
    5 select 'Mark', 'F' from dual union all 
    6 select 'Mark', 'E' from dual 
    7 ) 
    8 select * 
    9 from (select person, 
10     code, 
11     rank() over (partition by person 
12         order by (case when code='T' then 1 
13             when code='E' then 2 
14             when code='F' then 3 
15             else null 
16            end)) rnk 
17*   from data) 
SQL>/

PERS C  RNK 
---- - ---------- 
Mark E   1 
Mark F   2 
Paul T   1 
Paul E   2 
Tom F   1 

Elapsed: 00:00:00.00 

然後,你只需要選擇行的1

SQL> ed 
Wrote file afiedt.buf 

    1 with data as (
    2 select 'Tom' person, 'F' code from dual union all 
    3 select 'Paul', 'E' from dual union all 
    4 select 'Paul', 'T' from dual union all 
    5 select 'Mark', 'F' from dual union all 
    6 select 'Mark', 'E' from dual 
    7 ) 
    8 select * 
    9 from (select person, 
10     code, 
11     rank() over (partition by person 
12         order by (case when code='T' then 1 
13             when code='E' then 2 
14             when code='F' then 3 
15             else null 
16            end)) rnk 
17   from data) 
18* where rnk = 1 
SQL>/

PERS C  RNK 
---- - ---------- 
Mark E   1 
Paul T   1 
Tom F   1 

Elapsed: 00:00:00.00 
+1

如果(人員,代碼)可以重複使用'row_number()'而不是'rank()',並且只希望返回一個(任意選擇的)行。如果(人員,代碼)可以重複,並且您想要一行,並且您關心多行中的哪一行,則可以在'order by'中添加附加條件。您可能想考慮將代碼存儲到表中並加入,而不是將代碼編碼到存儲過程中。在某些情況下,這些好處將超出額外表格的缺點。 –

0

嗚嗚......與標準的SQL替代建議的RNK。 有一個CODE_WEIGHT表如:

CODE WEIGHT 
T 3  
E 2 
F 1 

然後組查詢由人(如果這是分組標準),並選擇包含max(weight)的不同的碼。

我會在一兩分鐘後的查詢。

UPDATE

好吧,抱歉的延遲。

下面是使用以前聲明表和@Randy招一個解決方案:

SELECT 
pp.person, decode(max(c.weight), 3, 'T', 2, 'E', 1, 'F', '') code 
FROM 
person pp INNER JOIN code_weight c on (pp.code = c.code) 
GROUP BY 
pp.person 
ORDER BY 
person DESC; 

我敢肯定有一種方法來轉儲甲骨文專有的功能和得到的東西在純SQL做...無論如何,因爲您已經要求提供Oracle解決方案了。

更新2

而且如許,這裏是最好的標準SQL版本,我能想出:

SELECT 
p.person, c.code 
FROM 
(
SELECT 
    pp.person, MAX(cc.weight) weight 
FROM 
    person pp INNER JOIN code_weight cc ON (pp.code = cc.code) 
GROUP BY 
    pp.person 
) p INNER JOIN code_WEIGHT c ON (p.weight = c.weight) 
ORDER BY 
    p.person DESC; 

有點兒醜與兩個加入......但它確實沒有專有擴展的工作。任何SQL大師都知道如何優化它?

乾杯,