Как задать условный номер строки по определенным значениям из таблицы

#sql #sql-server #sql-server-2008

Вопрос:

У меня есть запрос, который возвращает таблицу и основан на значении (если оно существует) Я хочу установить номер строки. У меня есть какое-то решение, но оно выглядит долгим, и я думаю, что могло бы быть проще и меньше кода (лучший вариант) для его обработки. Ниже приведен образец с ожидаемыми результатами:

Если запрос возвращает клиенту значение NULL:

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

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

Результат должен быть:

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

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

Если запрос возвращается без значения NULL:

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

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

Результат должен быть:

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

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

Ответ №1:

Я не уверен 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 » s » к другим значениям. Это тоже довольно просто:

 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;
 

Комментарии:

1. @LBman . . . Это более общий ответ, чем тот, который вы (в настоящее время) приняли, потому что он работает для любого числа NULL значений.

Ответ №2:

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;
 

Комментарии:

1. Спасибо @Luuk, но, как я уже сказал, запрос может возвращаться в некоторых случаях с «нулевым», а иногда и без «нулевого» клиента. Я хочу обработать его в одном запросе select, чтобы он охватывал оба сценария. Я думаю, мы могли бы добавить «когда существует», чтобы проверить и охватить оба сценария

Ответ №3:

 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;