CASE WHEN 的替代方案?

Alternative to CASE WHEN?

我在 SQL 中有一个 table,结果类似于:

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,return 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

问题是我不能说 if Number=1, return Name 2 in Name 3,因为我的 table 有 >100,000 条记录。我需要它自动完成。更像是 "if Number is the same, return Name 2 in Name 3." 我曾尝试使用 CASE 语句,但一直无法弄清楚。有什么办法吗?

根据经验,这似乎有效:

SELECT
    Number, Name, [Name 2],
    MAX([Name 2]) OVER (PARTITION BY Number) [Name 3]
FROM yourTable; 

这里的想法是,如果我正确解释了您的要求,您想要将 所有 记录的第二个名称的非 NULL 值报告为第三个名称值。

你可以试试这个:

解决方案 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 

方案二,有延迟(如果你的sql服务器版本有延迟功能)

SELECT
    Number, Name, Name2,
    isnull(Name2, lag(Name2) OVER (PARTITION BY Number order by number)) Name3
FROM @sample; 

解决方案 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

解决方案 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