2016-04-08 50 views
0

Toplama işlevini bir Pivot sorgusundan çıkarmak mümkün mü?Toplam işlev olmadan dönme

Bu soruna bir Sorunum var çünkü aynı doğum gününe sahip çalışanlar varsa, yalnızca birincisi görünür.

SELECT * 
FROM (SELECT lastname +' '+ firstname as name, Birthdate, 
     CASE 
     WHEN DATEPART(yyyy,Birthdate) BETWEEN 1930 AND 1939 THEN 1930 
     WHEN DATEPART(yyyy,Birthdate) BETWEEN 1940 AND 1949 THEN 1940 
     WHEN DATEPART(yyyy,Birthdate) BETWEEN 1950 AND 1959 THEN 1950 
     WHEN DATEPART(yyyy,Birthdate) BETWEEN 1960 AND 1969 THEN 1960 
     WHEN DATEPART(yyyy,Birthdate) BETWEEN 1970 AND 1979 THEN 1970 
     WHEN DATEPART(yyyy,Birthdate) BETWEEN 1980 AND 1989 THEN 1980 
     WHEN DATEPART(yyyy,Birthdate) BETWEEN 1990 AND 1999 THEN 1990 
     WHEN DATEPART(yyyy,Birthdate) BETWEEN 2000 AND 2009 THEN 2000 
     ELSE DATEPART(yyyy,Birthdate) END as [BDate] FROM ADR_Address 

) as s 
PIVOT 
(
    MAX(name) 
    FOR [BDate] IN ([1930],[1940],[1950],[1960],[1970],[1980],[1990],[2000]) 
)AS pvt 
WHERE Birthdate IS NOT NULL ORDER BY Birthdate 
+1

Bazı örnek veriler ekleyebilir misiniz? Ayrıca bir ipucu: Eğer (DATEPART (yyyy, Birthdate)/10) * 10) 'seçeneğini kullanırsanız,' case' ifadesinin tamamını kullanmazsınız ve yeni doğum günleri olduğunda 'CASE' 'e eklemeniz gerekmez. kapsamına gir. – HoneyBadger

+2

Ne tür sonuçlar almayı bekliyorsunuz? –

+0

@ user2210516 Y U ÖNEMLİ YA DA CEVAP ALABİLİRSİNİZ? –

cevap

0

Kodunuzu doğru anlıyorsam, döner satırlara başka bir ayırıcı, örneğin bir satır numarası ekleyebilirsiniz. Bu nedenle, Doğum günleri yerine, pivot satırlarda Doğum günleri + Orijinal satır numarası olacaktır.

teknik olarak bütün isimleri gösterebilir Bu şekilde ancak eksen bu tür hala garip: Bu konuda

SELECT lastname +' '+ firstname as name, 
     Birthdate, 
     ... 

:

SELECT * 
FROM (SELECT lastname +' '+ firstname as name, Birthdate, 
    CASE 
    WHEN DATEPART(yyyy,Birthdate) BETWEEN 1930 AND 1939 THEN 1930 
    WHEN DATEPART(yyyy,Birthdate) BETWEEN 1940 AND 1949 THEN 1940 
    WHEN DATEPART(yyyy,Birthdate) BETWEEN 1950 AND 1959 THEN 1950 
    WHEN DATEPART(yyyy,Birthdate) BETWEEN 1960 AND 1969 THEN 1960 
    WHEN DATEPART(yyyy,Birthdate) BETWEEN 1970 AND 1979 THEN 1970 
    WHEN DATEPART(yyyy,Birthdate) BETWEEN 1980 AND 1989 THEN 1980 
    WHEN DATEPART(yyyy,Birthdate) BETWEEN 1990 AND 1999 THEN 1990 
    WHEN DATEPART(yyyy,Birthdate) BETWEEN 2000 AND 2009 THEN 2000 
    ELSE DATEPART(yyyy,Birthdate) END as [BDate] 
    ,ROW_NUMBER() OVER (ORDER BY lastname +' '+ firstname) AS rn FROM ADR_Address 
) as s 
PIVOT 
(
    MAX(name) 
    FOR [BDate] IN ([1930],[1940],[1950],[1960],[1970],[1980],[1990],[2000]) 
)AS pvt 
WHERE Birthdate IS NOT NULL ORDER BY Birthdate 
0
set nocount on 
--http://stackoverflow.com/questions/36499843/pivoting-without-aggregate-function 
/*Logic in brief 
    -------------- 
    1) Work out the maximum number of rows to be output based on the largest number of rows in across birth decade/birth year 
    2) Create a dummy record for the number of rows calculated in 1) 
    3) Split by birth decade/birth year by allocating a counter(joinbylink) reset to 1 for every birth decade/birth year 
    4) Self join all the birth decade/birth year groups driven by the dummy record 
*/ 


declare @currentdecade int = 2000  --Dynmically control if listed by decade of birth or year of birth 
declare @dynamicsql varchar(200) 
declare @dynamicsql2 varchar(4000) 

if (exists (select * from INFORMATION_SCHEMA.TABLES where table_name = 'joins')) 
begin 
    drop table joins 
end 
if (exists (select * from INFORMATION_SCHEMA.TABLES where table_name = 'emp')) 
begin 
    drop table emp 
end 
if (exists (select * from INFORMATION_SCHEMA.TABLES where table_name = 'emp2')) 
begin 
    drop table emp2 
end 

create table joins      --Table to hold join statements for dynamic sql 
(joinstatement nchar(200)) 

create table emp      --employee table 
(
Name nchar(10), 
birthdate datetime, 
birthdecade int 
) 
insert into emp (name,birthdate) 
values ('jsmith',cast('1930/01/01' as datetime)), 
     ('jsmith',cast('1931/02/01' as datetime)), 
     ('abc',cast('1940/01/01' as datetime)), 
     ('def',cast('1950/01/01' as datetime)), 
     ('ghi',cast('1954/01/01' as datetime)), 
     ('jkl',cast('1950/01/01' as datetime)), 
     ('mno',cast('2000/01/01' as datetime)), 
     ('pqr',cast('2005/01/01' as datetime)) 

create table emp2      --employee table with a self join link 
(
Name nchar(10), 
birthdate datetime, 
birthdecade int, 
joinbylink int 
) 

update emp        --Work out birthdecade and decide if discrete year of birth should be maintained 
set birthdecade = 
    case 
    when year(birthdate)/10 * 10 = @currentdecade then year(birthdate) 
    else year(birthdate)/10 * 10 
    end 

declare @maxrows int = 0 
declare @loopcnt int = 1 
/*Find the max rows needed based on the maximum number of employes in a birth decade or birth year*/ 
SELECT @MAXROWS = MAXROWS FROM 
(
SELECT TOP 1 birthdecade,COUNT(*) MAXROWS FROM emp GROUP BY birthdecade order by count(*) desc 
) S 
/*Populate a table with maxrows of dummy records*/ 
while @loopcnt <= @maxrows 
begin 
insert into emp (NAME,birthdate,birthdecade) VALUES ('Dummy',cast('1900/01/01' as smalldatetime),1900) 
set @loopcnt = @loopcnt + 1 
end 


insert into emp2  --create a work table with a join by link 
select * ,row_number() over (partition by birthdecade order by birthdecade) from emp 


/*Generate join statements for use by dynamic sql*/ 
insert into joins 
select 'select emp' + cast(birthdecade as nchar(4)) +'.name as ' + char(39) + cast(birthdecade as nchar(4)) + char(39) 
FROM emp 
where birthdecade = 1900 
group by birthdecade order by birthdecade asc 

insert into joins 
select ',emp' + cast(birthdecade as nchar(4)) +'.name as ' + char(39) + cast(birthdecade as nchar(4)) + char(39) 
FROM emp 
where birthdecade <> 1900 
group by birthdecade order by birthdecade asc 

insert into joins 
select 'From emp2 as emp1900' 

insert into joins 
select 'Left join emp2 as emp' + cast(birthdecade as nchar(4)) + ' on emp' + cast(birthdecade as nchar(4)) + '.joinbylink = emp1900.joinbylink and emp' + cast(birthdecade as nchar(4)) + '.birthdecade = ' + cast(birthdecade as nchar(4)) 
FROM emp 
where birthdecade <> 1900 
group by birthdecade order by birthdecade asc 

insert into joins 
select 'where emp1900.birthdecade = 1900' 

/*for debug                                                                  
select a.joinbylink, a.name, 
     b.joinbylink, b.name '1930', 
     c.joinbylink, c.name '1940', 
     d.joinbylink, d.name '1950', 
     e.joinbylink, e.name '2000', 
     f.joinbylink, f.name '2005' 
from emp2 a 
left join emp2 b on b.joinbylink = a.joinbylink and b.birthdecade = 1930 
left join emp2 c on c.joinbylink = a.joinbylink and c.birthdecade = 1940 
left join emp2 d on d.joinbylink = a.joinbylink and d.birthdecade = 1950 
left join emp2 e on e.joinbylink = a.joinbylink and e.birthdecade = 2000 
left join emp2 f on f.joinbylink = a.joinbylink and f.birthdecade = 2005 
where a.birthdecade = 1900 
*/ 

/*Build a dynamic sql statement from join table and execute it*/ 

DECLARE db_cursor CURSOR FOR 
SELECT joinstatement 
FROM joins 

OPEN db_cursor 
FETCH next FROM db_cursor INTO @dynamicsql 
set @dynamicsql2 = rtrim(@dynamicsql) 
WHILE @@FETCH_STATUS = 0 
BEGIN 
     FETCH NEXT FROM db_cursor INTO @dynamicsql 
     if @@fetch_status = 0 
     begin 
      set @dynamicsql2 = @dynamicsql2 + ' ' + rtrim(@dynamicsql) 
     end 
END 

exec (@dynamicsql2) 

CLOSE db_cursor 
DEALLOCATE db_cursor 
0

Sorgunuzu bu bölümünü değiştirin:

SELECT lastname +' '+ firstname as name, 
     Birthdate, 
     ROW_NUMBER() OVER (ORDER BY Birthdate) as rn, 
     ...