SQL-запрос для диапазона дат, несколько раз начала / окончания - PullRequest
0 голосов
/ 21 июля 2010

В Microsoft SQL Server существует таблица с идентификатором записи, датой начала, датой окончания и количеством.

Идея состоит в том, что для каждой записи количество / общее количество дней в диапазоне = ежедневное количество.

Учитывая, что существует таблица, содержащая все возможные даты, как я могу сгенерировать набор результатов в SQL Server, чтобы он выглядел как в следующем примере?

EX:

RecordID | Start Date | End Date  | Quantity
1        |  1/1/2010  | 1/5/2010  | 30000
2        |  1/3/2010  | 1/9/2010  | 20000
3        |  1/1/2010  | 1/7/2010  | 10000

Results as
1        | 1/1/2010 |  QTY (I can do the math easy, just need the dates view)
1        | 1/2/2010 | 
1        | 1/3/2010 | 
1        | 1/4/2010 | 
1        | 1/3/2010 | 
2        | 1/4/2010 | 
2        | 1/5/2010 | 
2        | 1/6/2010 | 
2        | 1/7/2010 | 
2        | 1/8/2010 | 
2        | 1/9/2010 | 
3        | 1/1/2010 | 
3        | 1/2/2010 | 
3        | 1/3/2010 | 
3        | 1/4/2010 | 
3        | 1/5/2010 | 
3        | 1/6/2010 | 
3        | 1/7/2010 | 

Группировка по датам, которые я мог получить, затем получал сумму в тот день, однако окончательный набор результатов не может быть агрегирован из-за пользовательских фильтров, которые могут исключить некоторые из этих записей в будущем.

EDIT

Для пояснения, это всего лишь образец. Фильтры не имеют значения, так как я могу присоединиться к стороне, чтобы узнать подробности, связанные с идентификатором записи в результатах.

Реальные данные содержат N записей, которые увеличиваются еженедельно, даты никогда не совпадают. Может быть 2000 записей с разными датами начала и окончания ... Это то, для чего я хочу создать представление. Я могу присоединиться к данным и сделать то, что мне нужно

Я должен также упомянуть, что это для прошлых, настоящих и будущих данных. Я хотел бы избавиться от временной таблицы дат. Я использовал рекурсивный запрос, чтобы получить все даты, которые существуют в течение 50 лет, но это превышает пределы MAXRECURSION для представления, которое я не могу использовать.

Ответы [ 2 ]

3 голосов
/ 21 июля 2010

Ответ

select RecordId,d.[Date], Qty/ COUNT(*) OVER (PARTITION BY RecordId) AS Qty
from EX join Dates d on d.Date between [Start Date] and [End Date]
ORDER BY RecordId,[Date]

Примечание: в следующих демонстрационных CTE используется тип данных date, который представляет собой SQL Server 2008, хотя общий подход должен работать и для SQL2005.

Контрольный пример

/*CTEs for testing purposes only*/

WITH EX AS
(
    SELECT 1 AS RecordId, 
    cast('1/1/2010' as date) as [Start Date], 
    cast('1/5/2010' as date) as  [End Date], 
    30000 AS Qty
union all
    SELECT 2 AS RecordId, 
    cast('1/3/2010' as date) as [Start Date], 
    cast('1/9/2010' as date) as  [End Date], 
    20000  AS Qty
),Dates AS /*Dates Table now adjusted to do greater range*/
(

SELECT  DATEADD(day,s1.number + 2048*s2.number,'1990-01-01') AS [Date] 
FROM master.dbo.spt_values s1 CROSS JOIN master.dbo.spt_values s2
where s1.type='P' AND s2.type='P' and s2.number <= 8
order by  [Date] 
)


select RecordId,d.[Date], Qty/ COUNT(*) OVER (PARTITION BY RecordId) AS Qty
from EX join Dates d on d.Date between [Start Date] and [End Date]
ORDER BY RecordId,[Date]

Результаты

RecordId    Date       Qty
----------- ---------- -----------
1           2010-01-01 6000
1           2010-01-02 6000
1           2010-01-03 6000
1           2010-01-04 6000
1           2010-01-05 6000
2           2010-01-03 2857
2           2010-01-04 2857
2           2010-01-05 2857
2           2010-01-06 2857
2           2010-01-07 2857
2           2010-01-08 2857
2           2010-01-09 2857
1 голос
/ 21 июля 2010

Я думаю, вы можете попробовать это.

SELECT [Quantities].[RecordID], [Dates].[Date], SUM([Quantity])
FROM [Dates]
JOIN [Quantities] on [Dates].[Date] between [Quantities].[Start Date] and [End Date]
GROUP BY [Quantities].[RecordID], [Dates].[Date]
ORDER BY [Quantities].[RecordID], [Dates].[Date]
...