Sql 按值对行排序
我尝试按秩对表排序,但具有位置值的行必须根据位置字段中的值具有位置。是否可以在没有其他表、视图等的情况下执行此操作 我有这样的桌子:Sql 按值对行排序,sql,postgresql,Sql,Postgresql,我尝试按秩对表排序,但具有位置值的行必须根据位置字段中的值具有位置。是否可以在没有其他表、视图等的情况下执行此操作 我有这样的桌子: rank | position | name 999 | 10 | txt1 200 | 4 | txt2 32 | 1 | txt3 1200 | 2 | txt4 123 | null | txt5 234 | null | txt6 567 | null | txt7
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
所需的输出必须如下所示:
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
这里有一个想法。为每一行指定正确的顺序。然后,如果该职位可用,则使用该职位。当存在连接时,将位置值放在第一位:
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 Fiddle最近似乎不起作用,但此查询显示了结果:
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*。这里有一个想法。为每一行指定正确的顺序。然后,如果该职位可用,则使用该职位。当存在连接时,将位置值放在第一位:
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 Fiddle最近似乎不起作用,但此查询显示了结果:
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*。假设您将数据存储在表1中。 然后,您应该更新列位置,如下所示:
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
再见,
Angelo.假设您将数据存储在表1中。 然后,您应该更新列位置,如下所示:
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
再见,
Angelo.这是一个测试解决方案,但它有bug。例如,在大数字1234134的最后一行中,您可以看到更改排名,这是一个正在测试的解决方案,但它有错误。例如,如果在大数字1234134的最后一行更改排名,您可以看到它