2016-07-28 121 views
1

我嘗試按排名排序表,但具有位置值的行必須根據位置字段中的值進行排序。這可能沒有附加的表格,視圖等?按值對行排序

我的表是這樣的:

rank | position | name 
999 | 10  | txt1 
200 | 4  | txt2 
32 | 1  | txt3 
1200 | 2  | txt4 
123 | null  | txt5 
234 | null  | txt6 
567 | null  | txt7 
234 | null  | txt8 
432 | null  | txt9 
877 | null  | txt10 

所需的輸出必須是這樣的:

rank | position | name 
32 | 1  | txt3 
1200 | 2  | txt4 
877 | null  | txt10 
200 | 4  | txt2 
567 | null  | txt7 
432 | null  | txt9 
345 | null  | txt8 
234 | null  | txt6 
123 | null  | txt5  
999 | 10  | txt1 

回答

6

這是一個想法。爲每一行分配正確的順序。然後,如果該位置可用,則改爲使用該位置。當有關係,首先把position值:

select t.* 
from (select t.*, row_number() over (order by rank desc) as seqnum 
     from t 
    ) t 
order by (case when position is not null then position else seqnum end), 
     (case when position is not null then 1 else 2 end); 

SQL小提琴似乎並不奏效這些天,但此查詢演示結果:

with t(rank, position, t) as (
     select 999, 10, 'txt1' union all 
     select 200, 4, 'txt2' union all 
     select 32 , 1, 'txt3' union all 
     select 1200, 2, 'txt4' union all 
     select 123, null, 'txt5' union all 
     select 234, null, 'txt6' union all 
     select 567, null, 'txt7' union all 
     select 234, null, 'txt8' union all 
     select 432, null, 'txt9' union all 
     select 877, null , 'txt10' 
    ) 
select t.* 
from (select t.*, row_number() over (order by rank desc) as seqnum 
     from t 
    ) t 
order by (case when position is not null then position else seqnum end), 
     (case when position is not null then 1 else 2 end); 

編輯;

當我寫了上面的內容時,我有一個嘮叨的問題懷疑。這是一個應該工作的解決方案。這是更復雜的,但它產生正確的數字:

with t(rank, position, t) as (
     select 999, 10, 'txt1' union all 
     select 200, 4, 'txt2' union all 
     select 32 , 1, 'txt3' union all 
     select 1200, 2, 'txt4' union all 
     select 123, null, 'txt5' union all 
     select 234, null, 'txt6' union all 
     select 567, null, 'txt7' union all 
     select 234, null, 'txt8' union all 
     select 432, null, 'txt9' union all 
     select 877, null , 'txt10' 
    ) 
select * 
from (select t.*, g.*, 
      row_number() over (partition by t.position order by t.rank) gnum 
     from generate_series(1, 10) g(n) left join 
      t 
      on t.position = g.n 
    ) tg left join 
    (select t.*, 
      row_number() over (partition by t.position order by t.rank) as tnum 
     from t 
    ) t 
    on tg.gnum = t.tnum and t.position is null 
order by n; 

這是一個奇怪的交錯問題。這個想法是爲位置創建槽(使用生成系列)。然後,將已知位置分配給插槽。最後,枚舉剩餘的槽並在那裏分配值。

注:我硬編碼10,但很容易從表中放入count(*)

+0

這是有吸引力的解決方案,但它有錯誤。如果更改排名,您可以看到它,例如,在大數字的最後一行(1234134) – Nikitka

0

假設您將數據存儲在table1中。 那麼你應該更新列 「位置」,如下所示:

update a 
set position = x.pos_null 
from table1 
    a 
inner join 
    (
    select 
     a.name, 
     COUNT(a.rank) as pos_null 
    from 
     (
     select 
      * 
     from table1 
     where position is null 
     ) 
     a 
    left join 
     (
     select 
      *  
     from table1 
     ) 
     b 
     on a.rank <= b.rank 
    group by 
     a.name 
    ) 
    x 
    on a.name = x.name 


select * from table1 order by position 

再見, 安傑洛。