2

次の3つのテーブルがあります。

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

私が見つけようとしているのは、このすべてのデータを単一のテーブルに結合する最適な方法です。これは、本質的に各ジェダイのタイムラインです.

この場合の最終的なテーブルは次のとおりです。

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

今、私はこれに対する解決策を考え出しましたが、この状況ではうまく機能するカーソルを使用しますが、作業しているデータが非常に大きい場合は理想的ではありません.

SQL Server 2012 を使用しています。

余談ですが、これは「島」の問題の例ですか?

4

1 に答える 1

1

and (fromDate および toDate で)の代わりにandスキームを実行すると、すべてのDATEADDs を回避できます。>=<>=<=

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
于 2016-03-22T15:09:38.420 に答える