2011-08-12 24 views
0

SQL Server 2008:擬似SQLを実際の実行に変換するのは苦労しています。SQL Serverの連続/累積日

id, startdate, enddate 

をので、例えば:

1,1/1/2010,2/1/2010 
1,3/1/2010,3/15/2010 
2,4/1/2010,6/1/2010 
2,5/1/2010,5/15/2010 
2,7/1/2010,7/15/2010 

各IDが複数回記載されていることができ、日付が重なってできた場合要するに、私が持っているデータセットを持っています。

必要なもの:

)各IDの連続した日数を取得します。したがって、たとえば:

1 = 1/1/2010 thru 2/1/2010 + 3/1/2010 through 3/15/2010 = 43 
2 = 4/1/2010 thru 6/1/2010 + 7/1/2010 through 7/15/2010 (note: the 5/1/10 thru 5/15 was omitted because it overlapped) 

私の最初に考えたのは、これを行うだろうSQLクエリを記述することでした:

Date, ID, Active 

私は、全体の年間のデータを引っ張っていますので、私は/日を持っているでしょうテーブル内の各IDのIDエントリ。 「アクティブ」は、IDがその特定の日に「オン」であったかどうかに応じて1または0になります。

私はそれをグループ化して、その年のために私の「別個の」累積を得ることができました。

問題は、300,000,000,000以上のレコードを持つテーブルが作成され、これを行うためのより良い方法がないとは想像できません。

アドバイスをいただければ幸いです。

+0

それが唯一のフルオーバーラップされます(あなたの例を与える/ 5/1-5/15ワット)、または7/1-7/15と7/3-7/18のようなものがありますか?7/1-7/18 –

+0

あなたはアクティブでなくてもいいです。結果のデータ・セットにある行でDISTINCTを使用します。 – Natalia

答えて

1

私が正しくあなたの質問を理解していれば、これはあなたの結果

/*setup data*/ 
CREATE TABLE #dates 
(
     id INT, 
     startdate DATETIME, 
     enddate DATETIME 
) 

INSERT INTO #dates 
SELECT 1,'1/1/2010','2/1/2010' 
UNION ALL 
SELECT 1,'3/1/2010','3/15/2010' 
UNION ALL 
SELECT 2,'4/1/2010','6/1/2010' 
UNION ALL 
SELECT 2,'5/1/2010','5/15/2010' 
UNION ALL 
SELECT 2,'7/1/2010','7/15/2010' 


/* this is our "tally-table" maybe make this static*/ 
CREATE TABLE #numbers 
(
    NUM INT PRIMARY KEY CLUSTERED 
) 

;WITH Nbrs (n) AS (
     SELECT 1 UNION ALL 
     SELECT 1 + n FROM Nbrs WHERE n < 500) 
    INSERT INTO #numbers 
SELECT n FROM Nbrs 
    OPTION (MAXRECURSION 500) 

/*first we get our full range*/ 
;WITH fullrange 
AS 
(
    SELECT D.id, DATEADD(dd,N.num-1,D.startdate) AS dte 
    FROM #dates D 
     INNER JOIN #numbers N 
      ON N.num <= DATEDIFF(dd,D.startdate, D.enddate) 
      /*By joining to the numbers/tally table we can extrapolate the full range of dates like you alluded to in your considered approach*/ 
) 
/*then we aggregate*/ 
SELECT id, COUNT(DISTINCT dte) AS active --Now we can just count distinct dates for each id 
FROM fullrange 
GROUP BY id 
+0

ホーリー!@#!これは、私が行きたい道を私に教えてくれました!多くのありがとうございます。 – dpluscc

1

http://data.stackexchange.com/stackoverflow/q/109335/

DECLARE @tbl AS TABLE (id INT, startdate DATETIME, enddate DATETIME); 
INSERT INTO @tbl VALUES 
(1,'1/1/2010','2/1/2010') 
,(1,'3/1/2010','3/15/2010') 
,(2,'4/1/2010','6/1/2010') 
,(2,'5/1/2010','5/15/2010') 
,(2,'7/1/2010','7/15/2010'); 

WITH alldates AS (
    -- Adjust start date and number of days 
    SELECT TOP 100000 DATEADD(d, ROW_NUMBER() OVER(ORDER BY ac1.object_id) - 1, '1/1/2010') AS dt 
    FROM master.sys.all_columns ac1 
    CROSS JOIN master.sys.all_columns ac2 
) 
SELECT id, COUNT(DISTINCT alldates.dt) 
FROM alldates 
INNER JOIN @tbl AS period 
ON alldates.dt BETWEEN period.startdate AND period.enddate 
GROUP BY id; 
+0

これは良いアイデアです。マイクを選んだのは、私が自分の特定の状況に容易に成形できるからです。しかし、助けてくれてありがとう! – dpluscc