2017-01-17 6 views
2

Я использую SQL Server 2012. У меня есть таблица с ежедневной историей для суммы задержки, что-то вроде этого:Как получить минимальную дату по каждому разделу за один и тот же идентификатор разного времени? - SQL Server

SET DATEFORMAT YMD 
GO 
    CREATE TABLE [dbo].[testsum](
     [CID] [int], 
     [HDATE] [date], 
     [DELAYSUM] [numeric](16, 2) 
) 
GO 
INSERT [dbo].[testsum] ([CID], [HDATE], [DELAYSUM]) VALUES 
     (223,'2016-10-16',15503.80) 
     ,(223,'2016-10-17',15493.82) 
     ,(223,'2016-10-18',15489.25) 
     ,(223,'2016-10-19',15417.08) 
     ,(427,'2016-10-01',10375.89) 
     ,(427,'2016-10-02',10375.89) 
     ,(427,'2016-10-03',10385.91) 
     ,(427,'2016-10-16',8448.57) 
     ,(427,'2016-10-17',8443.13) 
     ,(427,'2016-10-18',8440.64) 
     ,(427,'2016-10-19',8401.31) 
     ,(427,'2016-10-20',8411.20) 
     ,(427,'2016-10-21',8414.58) 
     ,(427,'2016-10-22',8414.58) 
     ,(427,'2016-10-23',8414.58) 
     ,(427,'2016-10-24',8401.23) 
     ,(427,'2016-10-25',8393.92) 
     ,(427,'2016-10-26',8379.14) 
     ,(427,'2016-10-27',8374.57) 
     ,(427,'2016-10-28',8358.67) 
     ,(427,'2016-10-29',8358.67) 
     ,(427,'2016-10-30',8358.67) 
     ,(427,'2016-10-31',8346.61) 
     ,(541,'2016-10-05',900.44) 
     ,(541,'2016-10-06',832.84) 
     ,(541,'2016-10-11',637.54) 
     ,(541,'2016-10-15',413.89) 
     ,(541,'2016-10-16',413.89) 
     ,(541,'2016-10-17',413.89) 
     ,(541,'2016-10-18',1728.12) 
     ,(541,'2016-10-22',265.27) 
     ,(541,'2016-10-23',265.27) 
     ,(541,'2016-10-24',265.27) 
     ,(541,'2016-10-25',787.10) 
     ,(541,'2016-10-26',1222.29) 

Примера данные для 3 идентификаторов в октябре:

CID   HDATE  DELAYSUM 
    ----------- ---------- --------------------------------------- 
    223  2016-10-16 15503.80 
    223  2016-10-17 15493.82 
    223  2016-10-18 15489.25 
    223  2016-10-19 15417.08 
    427  2016-10-01 10375.89 
    427  2016-10-02 10375.89 
    427  2016-10-03 10385.91 
    427  2016-10-16 8448.57 
    427  2016-10-17 8443.13 
    427  2016-10-18 8440.64 
    427  2016-10-19 8401.31 
    427  2016-10-20 8411.20 
    427  2016-10-21 8414.58 
    427  2016-10-22 8414.58 
    427  2016-10-23 8414.58 
    427  2016-10-24 8401.23 
    427  2016-10-25 8393.92 
    427  2016-10-26 8379.14 
    427  2016-10-27 8374.57 
    427  2016-10-28 8358.67 
    427  2016-10-29 8358.67 
    427  2016-10-30 8358.67 
    427  2016-10-31 8346.61 
    541  2016-10-05 900.44 
    541  2016-10-06 832.84 
    541  2016-10-11 637.54 
    541  2016-10-15 413.89 
    541  2016-10-16 413.89 
    541  2016-10-17 413.89 
    541  2016-10-18 1728.12 
    541  2016-10-22 265.27 
    541  2016-10-23 265.27 
    541  2016-10-24 265.27 
    541  2016-10-25 787.10 
    541  2016-10-26 1222.29 

Необходимость вывода (минимальная дата для каждого раздела дат в идентификаторами (CID) с даты окончания каждого периода (секции)) Сегменты отделены друг от друга 1 или более дней:

CID   HDATE  DELAYSUM END_DATE 
    ----------- ---------- --------------------------------------- 
    223  2016-10-16 15503.80 2016-10-19 
    427  2016-10-01 10375.89 2016-10-03 
    427  2016-10-16 8448.57  2016-10-31 
    541  2016-10-05 900.44  2016-10-06 
    541  2016-10-11 637.54  2016-10-11 
    541  2016-10-15 413.89  2016-10-18 
    541  2016-10-22 265.27  2016-10-26 

Застыл с этой задачей на данный момент. Извините за мой английский.

ответ

1

Ключевым моментом здесь является для классификации записей в ИДС в той же группе, если разница между датой последовательных строк 1. Этот запрос использует логику dateadd(day,-row_number() over (partition by cid order by hdate),hdate), чтобы сделать это. Запустите внутренний запрос, чтобы узнать, как назначаются группы.

После этого, используя оконные функции min, max и first_value вы можете получить мин hdate, макс hdate и первое значение суммы задержки на CID с использованием групп ранее присвоенные.

SELECT DISTINCT cid, 
       min(hdate) over (partition BY cid, grp) AS hdate, 
       first_value(delaysum) over (partition BY cid, grp ORDER BY hdate) AS delaysum, 
       max(hdate) over (partition BY cid, grp) AS end_date 
FROM (SELECT t.* , 
     dateadd(DAY,-row_number() over (partition BY cid ORDER BY hdate),hdate) AS grp 
     FROM testsum t) x 
ORDER BY cid,hdate 

Sample Demo

+0

у круто! Thk u! –

0

Один из способов решения это разность номеров строк:

select cid, min(hdate), max(hdate), min(delaysum) 
from (select t.*, 
      row_number() over (order by hdate) as seqnum, 
      row_number() over (partition by cid order by hdate) as seqnum_c 
     from testsum t 
    ) t 
group by cid, (seqnum - seqnum_c); 

EDIT:

Когда я смотрю ближе, она выглядит, как вы хотите, первое значение, а не минимальное значение. SQL Server не предлагает first_value() (пока) как функцию агрегации. Итак:

select cid, min(hdate), max(hdate), min(first_delaysum) 
from (select t.*, 
      first_value(delaysum) over (partition by cid, seqnum - seqnum_c order by hdate) as first_delaysum 
     from (select t.*, 
        row_number() over (order by hdate) as seqnum, 
        row_number() over (partition by cid order by hdate) as seqnum_c 
      from testsum t 
      ) t 
    ) t 
group by cid, (seqnum - seqnum_c);     

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

  • Нет связанных вопросов^_^