Альтернатива на случай, когда?
У меня есть таблица в SQL, где результаты выглядят примерно так:
Number | Name | Name 2
1 | John | Derek
1 | John | NULL
2 | Jane | Louise
2 | Jane | NULL
3 | Michael | Mark
3 | Michael | NULL
4 | Sara | Paul
4 | Sara | NULL
Я хочу сказать, что если Number=1, верните Name 2 в новый столбец Name 3, чтобы результаты выглядели так:
Number | Name | Name 2 | Name 3
1 | John | Derek | Derek
1 | John | NULL | Derek
2 | Jane | Louise | Louise
2 | Jane | NULL | Louise
3 | Michael | Mark | Mark
3 | Michael | NULL | Mark
4 | Sara | Paul | Paul
4 | Sara | NULL | Paul
Проблема в том, что я не могу сказать, что если Number=1, вернуть Name 2 в Name 3, потому что в моей таблице>100 000 записей. Мне нужно сделать это автоматически. Больше похоже на "если число совпадает, вернуть имя 2 в имя 3". Я пытался использовать оператор CASE, но не смог понять это. Есть какой-либо способ сделать это?
5 ответов
Решение 2, с задержкой (если у вашей версии сервера sql есть функция задержки)
SELECT
Number, Name, Name2,
isnull(Name2, lag(Name2) OVER (PARTITION BY Number order by number)) Name3
FROM @sample;
Опытным путем это, кажется, работает:
SELECT
Number, Name, [Name 2],
MAX([Name 2]) OVER (PARTITION BY Number) [Name 3]
FROM yourTable;
Идея здесь, если я правильно истолковал ваши требования, заключается в том, что вы хотите сообщить о NULL
значение второго имени для всех записей в качестве значения третьего имени.
Решение 3, с группой по
with maxi as(
SELECT Number, max(Name2) name3
FROM @sample
group by number, name
)
SELECT f1.*, f2.name3
FROM @sample f1 inner join maxi f2 on f1.number=f2.number
Вы можете попробовать это:
Решение 1, с row_number
declare @sample table (Number integer, Name varchar(50), Name2 varchar(50))
insert into @sample
select 1 , 'John' , 'Derek' union all
select 1 , 'John' , NULL union all
select 2 , 'Jane' , 'Louise' union all
select 2 , 'Jane' , NULL union all
select 3 , 'Michael' , 'Mark' union all
select 3 , 'Michael' , NULL union all
select 4 , 'Sara' , 'Paul' union all
select 4 , 'Sara' , NULL ;
with tmp as (
select *, row_number() over(partition by number order by number) rang
from @sample
)
select f1.Number, f1.Name, f1.Name2, f2.Name2 as Name3
from tmp f1 inner join tmp f2 on f1.Number=f2.Number and f2.rang=1
Решение 4, с перекрестным применением
SELECT *
FROM @sample f1 cross apply
(
select top 1 f2.Name2 as Name3 from @sample f2
where f2.number=f1.number and f2.Name2 is not null
) f3