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
我在 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