Время по модулю в SQL Server 2005 — возвращайте данные каждые n часов

У меня есть что-то вроде этого:

 SELECt *
   FROM (
        SELECT prodid, date, time, tmp, rowid
          FROM live_pilot_plant
         WHERE date BETWEEN CONVERT(DATETIME, '3/19/2012', 101)
           AND CONVERT(DATETIME, '3/31/2012', 101)
         ) b
  WHERE b.rowid % 400 = 0

К вашему сведению: причина преобразования в предложении where заключается в том, что моя дата хранится как varchar (10), мне пришлось преобразовать ее в дату и время, чтобы получить правильный диапазон данных. (Я пробовал кучу разных вещей, и это сработало)

Мне интересно, как я могу возвращать данные, которые я хочу, каждые 4 часа в течение этих выбранных дат. У меня данные собираются примерно каждые 5 секунд (с некоторыми перерывами в данных), т.е. данные не собираются в течение 2-часового периода, а затем продолжаются с шагом в 5 секунд.

В моем примере я просто использовал модуль по модулю с моим rowid - и синтаксис работает, но, как я упоминал выше, есть некоторые периоды, когда данные не собираются, поэтому с помощью логики, например: если вы берете данные каждые 5 секунд и умножить на 4 часа, вы можете приблизительно сказать, сколько строк находится между ними, не получится.

Мой столбец времени представляет собой столбец varchar и имеет форму чч: мм: сс

Мой идеальный результат:

  | prodid  | date       | time      |  tmp  |
  |    4    | 3/19/2012  | 10:00:00  |  2.3  |
  |    7    | 3/19/2012  | 14:00:24  |  3.2  |

Как видите, я могу немного ошибиться (в секундах) - мне больше нужно приблизительное значение в терминах времени.

Заранее спасибо.


person akwarywo    schedule 31.07.2012    source источник


Ответы (3)


Это должно работать

select prodid, date, time, tmp, rowid
from live_pilot_plant as lpp
inner join (

select min(prodid) as prodid                     -- is prodid your PK?? if not change it to rowid or whatelse is your PK
    from live_pilot_plant
    WHERE date BETWEEN CONVERT(DATETIME, '3/19/2012', 101)  -- or whatever you want
                   AND CONVERT(DATETIME, '3/31/2012', 101)  -- for better performance it is on the inner select
    group by date, 
    floor(                                       -- floor makes the trick
    convert(float,convert(datetime, time))       -- assumes "time" column is a varchar containing data like '19:23:05'
    * 6                                          -- 6 comes form 24 hours / 4 hours
    )

) as filter on lpp.prodid = filter.prodid        -- if prodid is not the PK also correct here.

Дополнительное примечание для всех, у кого есть данные даты и времени только в одном поле даты и времени, предположим, с именем «когда_it_was», группа может быть такой простой, как:

group by floor(when_it_was * 6)                  -- again, 6 comes from 24/4
person Luis Siquot    schedule 31.07.2012
comment
Спасибо за помощь. Это круто. - person akwarywo; 01.08.2012

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

select * from (
select *,
row_number() over (partition by date,cast(left( time, charindex( ':', time) - 1) as int)  / 4 order by
date, time) as ranker  from live_pilot_plant
) Z where ranker = 1
person iruvar    schedule 31.07.2012

Предполагая, что rowid является PK и увеличивается с датой/временем. Просто преобразуйте поле времени в 4-часовой интервал с номером substring(time,1,2))/4 и выберите MIN(rowid) из каждой из 4-часовых групп в день:

select prodid, date, time, tmp, rowid from live_pilot_plant where rowid in
(
select min(rowid) 
from live_pilot_plant 
WHERE CONVERT(DATETIME, date, 101) BETWEEN CONVERT(DATETIME, '3/19/2012', 101)
           AND CONVERT(DATETIME, '3/31/2012', 101)
group by date,convert(int,substring(time,1,2))/4

)
order by CONVERT(DATETIME, date, 101),time
person valex    schedule 01.08.2012