2016-04-05 14 views
3

Bir tarih değerine dayanarak sütun başına son olmayan boş değer değerini seçmeye çalışıyorum.Sıfır olmayan sonraki değer nasıl seçilir? Her sütunda. T-SQL

Email   Name1 Name2 Job  Date 
[email protected] Ron  NULL NULL 2015-01-01 00:00:00.000 
[email protected] Dave Smith NULL 2014-01-01 00:00:00.000 
[email protected] NULL NULL NULL 2013-01-01 00:00:00.000 
[email protected] NULL Smith NULL 2014-01-01 00:00:00.000 
[email protected] NULL Ford Plumber 2015-01-01 00:00:00.000` 

Ben e-posta adresi başına her sütun için yeni boş olmayan değeri görüntülemek istiyorum -

Şöyle bir tablo var.

çıkışı olmalı - Zaten bu sorunu çözmek için bazı oldukça çirkin SQL yazdım

Email   Name1 Name2 Job 
[email protected] Ron  Smith NULL 
[email protected] NULL Ford Plumber 

ancak ben daha çok sütunlu başka bir tabloya bu mantığı uygulamak istiyor.

Soruma Soru: - Her bir sütuna katılmak zorunda kalmadan bunu yapmanın daha kolay bir yolu var mı? İşte

select distinct a.[Email],b.[Name1],c.[Name2],d.[job] from 
(
select [Email] from #test 
) 
A 
left join 
(
SELECT [Email], 
FIRST_VALUE([Name1]) over(partition by [Email] order by [Date] desc) as [Name1] 
from #test 
where [Name1] is not null 
) b 
on a.[Email] = b.[Email] 
left join 
(
SELECT [Email], 
FIRST_VALUE([Name2]) over(partition by [Email] order by [Date] desc) as [Name2] 
from #test 
where [Name2] is not null 
) c 
on a.[Email] = c.[Email] 
left join 
(
select [Email], 
FIRST_VALUE([Job]) over(partition by [Email] order by [Date] desc) as [Job] 
from #test 
where [Job] is not null 
) d 
on a.[Email] = d.[Email] 

bu yardımcı olur örnek tablo için DDL/DML var - - aşağıdaki gibi

Güncel çözümdür

create table #test 
([Email] nvarchar(50), 
[Name1] nvarchar(50), 
[Name2] nvarchar(50), 
[Job] nvarchar(50), 
[Date] datetime) 

insert into #test 
values 
('[email protected]', 'Ron', null,null,'20150101'), 
('[email protected]', 'Dave' ,'Smith',null, '20140101'), 
('[email protected]', null, null, null ,'20130101'), 
('[email protected]', null, 'Smith', null, '20140101'), 
('[email protected]', null, 'Ford', 'Plumber','20150101') 

cevap

2

Çok fazla katılma gerektirmeyen yollar var. Hiçbiri basit değildir, çünkü SQL Server, lag()'daki ignore nulls seçeneğini desteklemiyor.

Temel olarak, her bir sütunda mantık yapmanız gerekir. Bir alt sorgu olmadan bir yöntemdir:

select distinct email, 
     first_value(name1) over (partition by email 
           order by (case when name1 is not null then date else '2000-01-01' end) desc 
           ) as name1, 
     . . . 
from #test; 

alternatif dış kullanır geçerlidir:

select t.email, name1, . . . 
from (select distinct email from #test t) t outer apply 
    (select top 1 name1 
     from #test t2 
     where t2.email = t.email and name1 is not null 
     order by date desc 
    ) name1 . . . 
2

kullanabilirsiniz FIRST_VALUEDISTINCT ile:

SELECT DISTINCT Email, 
     FIRST_VALUE(Name1) OVER (PARTITION BY Email 
           ORDER BY CASE 
              WHEN Name1 IS NULL THEN '19000101' 
              ELSE [Date] 
             END DESC) AS Name1, 
     FIRST_VALUE(Name2) OVER (PARTITION BY Email 
           ORDER BY CASE 
              WHEN Name2 IS NULL THEN '19000101' 
              ELSE [Date] 
             END DESC) AS Name2, 
     FIRST_VALUE(Job) OVER (PARTITION BY Email 
           ORDER BY CASE 
              WHEN Job IS NULL THEN '19000101' 
              ELSE [Date] 
             END DESC) AS Job 
FROM test 
İlgili konular