2015-07-07 2 views
0

У меня есть ежедневные измерения помещения для хранения температуры в таблице (отдельной таблице для каждой комнаты):Зерноуборочных интервалы дат от 2 таблиц

 
begindate | enddate | temperature | room_id 
-------------------------------------------- 
1/1/2014 | 1/2/2014 | 10   | 1 
1/2/2014 | 1/3/2014 | 12   | 1 
1/4/2014 | 1/5/2014 | 11   | 1 
1/5/2014 | 1/6/2014 | 12   | 1 
1/6/2014 | 1/7/2014 | 10   | 1 
1/7/2014 | 1/8/2014 | 11   | 1 
1/8/2014 | 1/9/2014 | 12   | 1 
...... 
1/29/2014 | 1/30/2014| 10   | 1 
1/30/2014 | 1/31/2014| 12   | 1 
1/31/2014 | 2/1/2014 | 10   | 1 
...... 
3/1/2014 | 3/2/2014 | 14   | 1 
..... 
Does not show all dates but the measurements are daily 

Второй таблица содержит даты, когда помещение для хранения было занят

 
begindate | enddate | room_id 
--------------------------------- 
1/6/2014 | 1/9/2014 | 1 
1/15/2014 | 1/29/2014 | 1 
3/1/2014 | 3/2/2014 | 1 

Мне нужна средняя температура в помещении во время ее занятости или месячной температуры в том случае, если комната не была занята или занята в течение более чем одного месяца. С учетом указанных выше данных, результат должен быть что-то вроде:

 
begindate | enddate | avg_temp | room_id 
-------------------------------------------------- 
1/1/2014  | 1/6/2014 | 11  | 1 
1/6/2014  | 1/9/2014 | 11  | 1 
1/9/2014  | 1/15/2014 | 11  | 1 
1/15/2014 | 1/29/2014 | 12  | 1 
1/29/2014 | 2/1/2014 | 11  | 1 
2/1/2014  | 3/1/2014 | 13  | 1 
3/1/2014  | 3/2/2014 | 14  | 1 
3/2/2014  | 4/1/2014 | 15  | 1 

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

код создают температуру данных таблицы:

 
INSERT INTO @temps 
values 
('01/01/2014','01/02/2014','10','1'), 
('01/02/2014','01/03/2014','12','1'), 
('01/03/2014','01/04/2014','11','1'), 
('01/04/2014','01/05/2014','11','1'), 
('01/05/2014','01/06/2014','12','1'), 
('01/06/2014','01/07/2014','10','1'), 
('01/07/2014','01/08/2014','11','1'), 
('01/08/2014','01/09/2014','12','1'), 
('01/09/2014','01/10/2014','10','1'), 
('01/10/2014','01/11/2014','12','1'), 
('01/11/2014','01/12/2014','10','1'), 
('01/12/2014','01/13/2014','10','1'), 
('01/13/2014','01/14/2014','11','1'), 
('01/14/2014','01/15/2014','12','1'), 
('01/15/2014','01/16/2014','11','1'), 
('01/16/2014','01/17/2014','14','1'), 
('01/17/2014','01/18/2014','12','1'), 
('01/18/2014','01/19/2014','10','1'), 
('01/19/2014','01/20/2014','11','1'), 
('01/20/2014','01/21/2014','10','1'), 
('01/21/2014','01/22/2014','11','1'), 
('01/22/2014','01/23/2014','12','1'), 
('01/23/2014','01/24/2014','11','1'), 
('01/24/2014','01/25/2014','14','1'), 
('01/25/2014','01/26/2014','12','1'), 
('01/26/2014','01/27/2014','10','1'), 
('01/27/2014','01/28/2014','11','1'), 
('01/28/2014','01/29/2014','10','1'), 
('01/29/2014','01/30/2014','11','1'), 
('01/30/2014','01/31/2014','12','1'), 
('01/31/2014','02/01/2014','11','1'), 
('02/01/2014','02/02/2014','14','1'), 
('02/02/2014','02/03/2014','12','1'), 
('02/03/2014','02/04/2014','10','1'), 
('02/04/2014','02/05/2014','11','1'), 
('02/05/2014','02/06/2014','10','1'), 
('02/06/2014','02/07/2014','11','1'), 
('02/07/2014','02/08/2014','12','1'), 
('02/08/2014','02/09/2014','11','1'), 
('02/09/2014','02/10/2014','14','1'), 
('02/10/2014','02/11/2014','12','1'), 
('02/11/2014','02/12/2014','10','1'), 
('02/12/2014','02/13/2014','11','1'), 
('02/13/2014','02/14/2014','10','1'), 
('02/14/2014','02/15/2014','11','1'), 
('02/15/2014','02/16/2014','12','1'), 
('02/16/2014','02/17/2014','11','1'), 
('02/17/2014','02/18/2014','14','1'), 
('02/18/2014','02/19/2014','12','1'), 
('02/19/2014','02/20/2014','10','1'), 
('02/20/2014','02/21/2014','11','1'), 
('02/21/2014','02/22/2014','10','1'), 
('02/22/2014','02/23/2014','11','1'), 
('02/23/2014','02/24/2014','12','1'), 
('02/24/2014','02/25/2014','11','1'), 
('02/25/2014','02/26/2014','14','1'), 
('02/26/2014','02/27/2014','12','1'), 
('02/27/2014','02/28/2014','15','1'), 
('02/28/2014','03/01/2014','11','1'), 
('03/01/2014','03/02/2014','11','1'), 
('03/02/2014','03/03/2014','12','1'), 
('03/03/2014','03/04/2014','11','1'), 
('03/04/2014','03/05/2014','14','1'), 
('03/05/2014','03/06/2014','12','1'), 
('03/06/2014','03/07/2014','15','1'), 
('03/07/2014','03/08/2014','11','1'), 
('03/08/2014','03/09/2014','12','1'), 
('03/09/2014','03/10/2014','11','1'), 
('03/10/2014','03/11/2014','14','1'), 
('03/11/2014','03/12/2014','12','1'), 
('03/12/2014','03/13/2014','15','1'), 
('03/13/2014','03/14/2014','11','1'), 
('03/14/2014','03/15/2014','12','1'), 
('03/15/2014','03/16/2014','11','1'), 
('03/16/2014','03/17/2014','14','1'), 
('03/17/2014','03/18/2014','12','1'), 
('03/18/2014','03/19/2014','15','1'), 
('03/19/2014','03/20/2014','11','1'), 
('03/20/2014','03/21/2014','12','1'), 
('03/21/2014','03/22/2014','11','1'), 
('03/22/2014','03/23/2014','14','1'), 
('03/23/2014','03/24/2014','12','1'), 
('03/24/2014','03/25/2014','15','1'), 
('03/25/2014','03/26/2014','11','1'), 
('03/26/2014','03/27/2014','12','1'), 
('03/27/2014','03/28/2014','11','1'), 
('03/28/2014','03/29/2014','14','1'), 
('03/29/2014','03/30/2014','12','1'), 
('03/30/2014','03/31/2014','15','1'), 
('03/31/2014','04/01/2014','11','1'), 
('04/01/2014','04/02/2014','12','1'), 
('04/02/2014','04/03/2014','11','1'), 
('04/03/2014','04/04/2014','14','1'), 
('04/04/2014','04/05/2014','12','1'), 
('04/05/2014','04/06/2014','15','1') 

+3

Пожалуйста, ваши попытки в решении этого, поэтому мы можем помочь вам определить, что пошло неправильно. –

ответ

0

Может что-то вроде этого быть, что вам нужно?

Мой подход, чтобы дать периоды ключ и использовать либо период или year_month как ключ для разделения Avg-функции (OVER пункта: https://msdn.microsoft.com/en-us/library/ms189461.aspx)

EDIT: Новый подход, как О.П. нужно что-то Остальное:

ЗАМЕЧАНИЕ: Если «свободный» период должен заканчиваться там, где начинается реальный период, и после окончания реального периода должен появиться новый «свободный» период, я мог бы предложить другой подход, но это много в одном ответе. Пожалуйста, дайте мне знать ...

EDIT: Мой «Примечание» было именно в этом, поэтому я предлагаю другой подход:

SET LANGUAGE English; 

DECLARE @rooms TABLE(roomID INT,room VARCHAR(10)); 
INSERT INTO @rooms VALUES(1,'Room 1'),(2,'Room 2'); 

DECLARE @temps TABLE(begD DATE, endD DATE,temp INT, roomID INT); 
INSERT INTO @temps 
VALUES('1/1/2014','1/2/2014','10','1') 
    ,('1/2/2014','1/3/2014','12','1') 
    ,('1/4/2014','1/5/2014','11','1') 
    ,('1/5/2014','1/6/2014','12','1') 
    ,('1/6/2014','1/7/2014','10','1') 
    ,('1/7/2014','1/8/2014','11','1') 
    ,('1/8/2014','1/9/2014','12','1') 
    ,('1/29/2014','1/30/2014','10','1') 
    ,('1/30/2014','1/31/2014','12','1') 
    ,('1/31/2014','2/1/2014','10','1') 
    ,('3/1/2014','3/2/2014','14','1'); 

DECLARE @periods TABLE(periodID INT, begD DATE,endD DATE,roomID INT); 
INSERT INTO @periods 
VALUES(1,'1/6/2014','1/9/2014','1') 
    ,(2,'1/15/2014','1/29/2014','1') 
    ,(3,'3/1/2014','3/2/2014','1'); 

DECLARE @StartDate DATE='1/1/2014'; 
DECLARE @DayCount INT=50; 
WITH dayList AS 
(
    SELECT TOP (@DayCount) DATEADD(d,numbers.nr-1,@StartDate) AS dayDate 
    FROM 
    (
     SELECT ROW_NUMBER() OVER(ORDER BY o.object_id) FROM sys.objects AS o 
    ) AS numbers(nr) 
) 
,roomDayList AS 
(
    SELECT dayList.dayDate,r.* 
    FROM dayList,@rooms AS r 

) 
,occupations AS 
(
    SELECT roomDayList.dayDate 
      ,roomDayList.roomID 
      ,roomDayList.room 
      ,ISNULL(InPeriod.PeriodID,'free') AS PeriodID 
    FROM roomDayList 
    OUTER APPLY 
    (
     SELECT 'P'+CAST(periodID AS VARCHAR(MAX)) AS PeriodID 
     FROM @periods AS p 
     WHERE p.roomID=roomDayList.roomID 
      AND roomDayList.dayDate BETWEEN p.begD AND p.endD 
    ) InPeriod 
) 
,periodBorders AS 
(
    SELECT tbl.* 
    FROM 
    (
     SELECT occupations.* 
       ,CASE WHEN [email protected] THEN @StartDate ELSE CASE WHEN occupations.PeriodID<>RowBefore.PeriodID THEN occupations.dayDate ELSE NULL END END AS FirstDayOfPeriod 
       ,CASE WHEN occupations.dayDate=(SELECT MAX(dayDate) FROM dayList) THEN (SELECT MAX(dayDate) FROM dayList) ELSE CASE WHEN occupations.PeriodID<>RowAfter.PeriodID THEN occupations.dayDate ELSE NULL END END AS LastDayOfPeriod 
     FROM occupations 
     OUTER APPLY 
     (
      SELECT PeriodID 
      FROM occupations AS innerOc 
      WHERE innerOc.dayDate=DATEADD(d,-1,occupations.dayDate) 
       AND innerOc.roomID=occupations.roomID 
     ) AS RowBefore 
     OUTER APPLY 
     (
      SELECT PeriodID 
      FROM occupations AS innerOc 
      WHERE innerOc.dayDate=DATEADD(d,1,occupations.dayDate) 
       AND innerOc.roomID=occupations.roomID 
     ) AS RowAfter 
    ) AS tbl 
    WHERE tbl.FirstDayOfPeriod IS NOT NULL OR tbl.LastDayOfPeriod IS NOT NULL 
) 
,mergeBorders AS 
(
    SELECT periodBorders.dayDate 
      ,periodBorders.roomID 
      ,periodBorders.room 
      ,periodBorders.PeriodID 
      ,periodBorders.FirstDayOfPeriod 
      ,ISNULL(periodBorders.LastDayOfPeriod,PeriodEndDate.dt) AS LastDayOfPeriod 
    FROM periodBorders 
    CROSS APPLY 
    (
     SELECT TOP 1 pB.LastDayOfPeriod FROM periodBorders AS pB WHERE pB.roomID=periodBorders.roomID AND pB.dayDate>periodBorders.dayDate ORDER BY pB.dayDate ASC 
    ) AS PeriodEndDate(dt) 
    WHERE periodBorders.FirstDayOfPeriod IS NOT NULL 
) 
,tempMeasures AS 
(
    SELECT t.temp 
      ,Period.* 
    FROM @temps AS t 
    CROSS APPLY 
    (
     SELECT * 
     FROM mergeBorders 
     WHERE mergeBorders.roomID=t.roomID AND t.begD BETWEEN mergeBorders.FirstDayOfPeriod AND mergeBorders.LastDayOfPeriod 
    ) AS Period 
) 
SELECT t.roomID 
     ,t.FirstDayOfPeriod 
     ,t.LastDayOfPeriod 
     ,AVG(t.temp) 
FROM tempMeasures AS t 
GROUP BY t.FirstDayOfPeriod,t.LastDayOfPeriod,t.roomID 
ORDER BY t.roomID,t.FirstDayOfPeriod 
+0

Спасибо, что я могу начать работать, но мне нужно иметь только одну запись за период с датой начала и окончания периода. – user2250303

+0

Еще одно предложение: я отредактирую свой ответ, пожалуйста, посмотрите его там (и не забывайте о повышении, если это вам поможет :-)) – Shnugo

+0

Ну, я думаю, проблема начинается, когда вы группируете: у нас теперь есть перекрывающиеся интервалы. Например, существует интервал дат 1/1/2014 - 1/31/2014, который охватывает 2 других интервала - 1/6/2014 - 1/9/2014 и 1/15/2014 - 1/29/2014. Вместо этих трех интервалов мы должны иметь 1/1/2014 до 1/6/2014, 1/6/2014 - 1/9/2014, 1/9/2014 по 1/15/2014, 15.01.2012 до 1/29/2014, и с 1/29/2014 по 1/1/2014. – user2250303

Смежные вопросы