Последовательные / накопительные даты в SQL Server - PullRequest
0 голосов
/ 12 августа 2011

SQL Server 2008: мне трудно переводить псевдо-SQL в фактическое выполнение. Короче говоря, у меня есть набор данных, который имеет:

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

Где каждый идентификатор может быть указан несколько раз, а даты могут совпадать.

Мне нужно:

а) Получите дни подряд для каждого удостоверения личности. Так, например:

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

Я собираю данные за весь год, поэтому у меня будет запись даты / идентификатора для каждого идентификатора в таблице. Значение «активный» будет равно 1 или 0 в зависимости от того, был ли этот идентификатор «включен» для данного конкретного дня.

Тогда я мог бы сгруппировать это и получить свою "отличную" совокупную сумму за год.

Проблема в том, что будет создана таблица с более чем 300 000 000 миллионами записей, и я просто не могу представить, что нет лучшего способа сделать это.

Любой совет будет принят с благодарностью.

Ответы [ 2 ]

1 голос
/ 12 августа 2011

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;
1 голос
/ 12 августа 2011

Если я правильно понимаю ваш вопрос, это даст вам ваши результаты

/*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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...