2016-03-22 20 views
2

Aşağıdaki 3 tablolar vardır:SQL Server birden çok tablolarla bir zaman çizelgesi oluşturma

CREATE TABLE Jedi (
jediId INT NOT null, 
name nvarchar(100) NOT NULL, 
jediRank nvarchar(100) NOT NULL, 
fromDate Date NOT NULL, 
toDate Date NOT NULL 
) 

INSERT INTO Jedi(jediId, name, jediRank, fromdate, todate) 
SELECT 666 jediId, 'A.Skywalker' name, 'padawan' jediRank, '1990-01-01' fromDate, '1999-12-31' toDate Union 
SELECT 666 jediId, 'A.Skywalker' name, 'Jedi Knight' jediRank, '2000-01-01' fromDate, '2005-06-17' toDate Union 
SELECT 666 jediId, 'A.Skywalker' name, 'Jedi Master' jediRank, '2005-06-18' fromDate, '2005-09-28' toDate Union 
SELECT 666 jediId, 'D.Vader' name, 'Sith Apprentice' jediRank, '2005-09-29' fromDate, '9999-12-31' toDate 
ORDER BY jediId, fromdate, todate 

CREATE TABLE lightsaberColors (
jediId int, 
lightsaberColor nvarchar(100) NOT NULL, 
fromDate Date NOT NULL, 
toDate Date NOT NULL 
) 

INSERT INTO lightsaberColors(jediId, lightsaberColor, fromdate, todate) 
SELECT 666, 'blue' color, '1990-01-01' fromdate, '1992-01-01' todate UNION 
SELECT 666, 'green' color, '1992-01-02' fromdate, '1992-04-15' todate UNION 
SELECT 666, 'blue' color, '1992-04-16' fromdate, '2005-09-30' todate UNION 
SELECT 666, 'red' color, '2005-10-01' fromdate, '9999-12-31' todate 
ORDER BY fromdate, todate 

CREATE TABLE mechanicalbodyparts (
jediId int, 
mechanicalBodyPart nvarchar(100) NOT NULL, 
fromDate Date NOT NULL, 
toDate Date NOT NULL 
) 
INSERT INTO mechanicalbodyparts(jediId, mechanicalBodyPart,fromDate, toDate) 
SELECT 666, 'N/A' mechanicalBodyPart, '1990-01-01' fromdate, '1998-05-13' todate UNION 
SELECT 666, 'hand and arm' mechanicalBodyPart, '1998-05-14' fromdate, '2005-09-29' todate UNION 
SELECT 666, 'pretty much everything' mechanicalBodyPart, '2005-09-30' fromdate, '9999-12-31' todate 
ORDER BY fromdate, todate 

SELECT * From jedi ORDER BY fromdate 
SELECT * From lightsaberColors ORDER BY fromdate 
SELECT * From mechanicalbodyparts ORDER BY fromdate 

ve ne bulmaya çalışıyorum aslında tek bir tabloya tüm bu verileri birleştirerek en uygun yoldur her jedi için zaman çizelgesi.

Ben bu durumda sona ereceğini tablodur: Şimdi, bunun için bir çözüm gelmiş

CREATE TABLE JediTimeline(
jediId Int NOT null, 
fromDate date NOT null, 
toDate date NOT NULL, 
name nvarchar(100) NOT NULL, 
jediRank nvarchar(100) NOT NULL, 
mechanicalBodyPart nvarchar(100) NOT NULL, 
lightsaberColor nvarchar(100) NOT NULL 
) 

INSERT INTO JediTimeline (jediId, fromDate, toDate, name, jediRank, mechanicalBodyPart, lightsaberColor) 
Select 666, '1990-01-01', '1992-01-01', 'A.Skywalker', 'padawan', 'N/A', 'blue' Union 
Select 666, '1992-01-02', '1992-04-15', 'A.Skywalker', 'padawan', 'N/A', 'green' Union 
Select 666, '1992-04-16', '1998-05-13', 'A.Skywalker', 'padawan', 'N/A', 'blue' Union 
Select 666, '1998-05-14', '1999-12-31', 'A.Skywalker', 'padawan', 'hand and arm', 'blue' Union 
Select 666, '2000-01-01', '2005-06-17', 'A.Skywalker', 'Jedi Knight', 'hand and arm', 'blue' Union 
Select 666, '2005-06-18', '2005-09-28', 'A.Skywalker', 'Jedi Master', 'hand and arm', 'blue' Union 
Select 666, '2005-09-29', '2005-09-29', 'D.Vader', 'Sith Apprentice', 'hand and arm', 'blue' Union 
Select 666, '2005-09-30', '2005-09-30', 'D.Vader', 'Sith Apprentice', 'pretty much everything', 'blue' Union 
Select 666, '2005-10-01', '9999-12-31', 'D.Vader', 'Sith Apprentice', 'pretty much everything', 'red' 
ORDER BY 1,2,3 


SELECT * 
FROM JediTimeline 

ama bu durumda çalışıyor ama onun ideal değil bir imleç kullandığında Çalıştığım veriler çok daha büyük. Ben SQL Server Yan not 2012.

ile çalışıyorum

, bu bir 'Adaları' sorunun örneğidir? Eğer bir >= ve < düzeni çalıştırırsanız

+0

Muhtemelen overkill ama bu SQL Server Analysis Services (OLAP) için mükemmel sesler –

+0

Evet, başka bir boşluk ve ada sorunu için bu düzgün bir örnek. Yine de, seninki, çeşitli boşluklar ve adalar üzerindeki bindirmelerle. Her neyse, muhtemelen etiketi sorgunuza eklemelisiniz: [boşluklar ve adalar] (http://stackoverflow.com/questions/tagged/gaps-and-islands) – Ralph

+0

@JohnHartsock - Bunu SSAS'da nasıl yaparsınız? Sanırım şu an bir T-SQL çözümü tercih ediyorum ama bunu SSAS'da nasıl yapacağınızla ilgilenirim. – Liv

cevap

1

tamamı DATEADD ler yerine >= ve <= arasında (FROMTarih ve Todate), önlenebilirdi.

with 
    UniqueCutoffDates as (
     select distinct fromDate as cutoff, jediId from Jedi union 
     select distinct fromDate,   jediId from lightsaberColors union 
     select distinct fromDate,   jediId from mechanicalbodyparts union 

     select distinct DATEADD(d,1,toDate), jediId from Jedi    where toDate <> '9999-12-31' union 
     select distinct DATEADD(d,1,toDate), jediId from lightsaberColors where toDate <> '9999-12-31' union 
     select distinct DATEADD(d,1,toDate), jediId from mechanicalbodyparts where toDate <> '9999-12-31' 
    ) 

select 
    jedi.jediId, 
    dates.cutoff as fromDate, 
    DATEADD(d,-1,LEAD(dates.cutoff,1,'9999-12-31') OVER (partition by jedi.jediId order by dates.cutoff)) as toDate, 
    jedi.name, 
    jedi.jediRank, 
    body.mechanicalBodyPart, 
    colors.lightsaberColor 
from 
    UniqueCutoffDates dates 
    inner join Jedi on 
     jedi.fromDate <= dates.cutoff and 
     Jedi.toDate > DATEADD(d,-1,dates.cutoff) and 
     jedi.jediId = dates.jediId 
    inner join lightsaberColors colors on 
     colors.fromDate <= dates.cutoff and 
     colors.toDate > DATEADD(d,-1,dates.cutoff) and 
     colors.jediId = jedi.jediId 
    inner join mechanicalbodyparts body on 
     body.fromDate <= dates.cutoff and 
     body.toDate > DATEADD(d,-1,dates.cutoff) and 
     body.jediId = jedi.jediId 
İlgili konular