如何通过 table 中的特定值设置条件行号

How to set Conditional Row Number by specific values from the table

我有一个查询 returns table 并且基于值(如果存在)我想设置 row_number。 我有一些解决方案,但它看起来很长,我认为处理它可能更容易,代码更少(最佳选择)。以下示例具有预期结果:

如果查询 returns Client with NULL:

----------------------
Process | Client|

  A     | NULL  |
  A     | B     |
  A     | B     |
  A     | B     |
  A     | C     |
  A     | C     |
  A     | C     |

OutPut 应该是:

    ----------------------
Process | Client| RowNumber

  A     | NULL  | 1
  A     | B     | 2
  A     | B     | 3
  A     | B     | 4
  A     | C     | 2
  A     | C     | 3
  A     | C     | 4

如果查询 returns 没有 NULL:

----------------------
Process | Client|

  A     | B     |
  A     | B     |
  A     | B     |
  A     | C     |
  A     | C     |
  A     | C     |

OutPut 应该是:

    ----------------------
Process | Client| RowNumber

  A     | B     | 1
  A     | B     | 2
  A     | B     | 3
  A     | C     | 1
  A     | C     | 2
  A     | C     | 3

我不确定 NULL 是否应该始终被视为 'B',但你需要处理它:

select t.* ,
       row_number() over (partition by process, coalesce(client, 'B') order by (select null))
from t
where client is not null;

哦,我明白了,您不是将 NULL 设置为 'B',而是将 NULL 的数量添加到其他值。这也很简单:

select t.* ,
       (row_number() over (partition by process, client order by (select null)) +
        (case when client is null then 0
               else sum(case when client is null then 1 else 0 end) over ()
         end)
       )
from t
where client is not null;

dbfiddle


DROP TABLE if exists mytable;
CREATE TABLE mytable(Process char(1), Client char(1));

INSERT INTO mytable values
  ('A',null),
  ('A','B'),
  ('A','B'),
  ('A','B'),
  ('A','C'),
  ('A','C'),
  ('A','C');


-- with a NULL value
select 
   Process, 
   Client, 
   ROW_NUMBER() OVER (partition by process,Client order by (select null))+CASE WHEN Client is null THEN 0 else 1 end R 
from mytable;

-- without a NULL value
select 
   Process, 
   Client, 
   ROW_NUMBER() OVER (partition by process,Client order by (select null)) R 
from mytable
where not client is null;

declare @t table(process varchar(10), client varchar(10));

insert into @t(process, client)
values
('A', null),
('A', 'B'),('A', 'B'),('A', 'B'),
('A', 'C'),('A', 'C'),
('A', ''), ('A', ''), ('A', ' '), ('A', ' '), 
('A', 'ZXY'), ('A', 'ZXY'),
('X', 'B'),('X', 'B'),('X', 'B'),
('X', 'C'),('X', 'C');

select *, 
row_number() over(partition by process,client order by client)
--if there is a null client per process then add 1 to every non null client
+ case when client is not null and min(case when client is null then 0 else 1 end) over(partition by process) = 0 then 1 else 0 end
--+ case when client is not null and min(isnull(ASCII(client+'.'), 0)) over(partition by process) = 0 then 1 else 0 end
as rownumber
from 
(
select * 
from @t
--where client is not null
) as t;