시간 또는 10 분 단위로 시간을 그룹화하는 방법


167

내가 할 때처럼

SELECT [Date]
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY [Date]

그룹 기간을 어떻게 지정할 수 있습니까?

MS SQL 2008

2 차 편집

노력하고있어

SELECT MIN([Date]) AS RecT, AVG(Value)
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY (DATEPART(MINUTE, [Date]) / 10)
  ORDER BY RecT

% 10을 / 10으로 변경했습니다. 밀리 초없이 날짜를 출력 할 수 있습니까?

답변:


213

마지막으로 완료

GROUP BY
DATEPART(YEAR, DT.[Date]),
DATEPART(MONTH, DT.[Date]),
DATEPART(DAY, DT.[Date]),
DATEPART(HOUR, DT.[Date]),
(DATEPART(MINUTE, DT.[Date]) / 10)

11
나는 그것을 만든 ROUND((DATEPART(MINUTE, DT.[Date]) / 5),0,1) * 5, 그래서이 데이터를 볼 때 가장 가까운 타임 슬롯과 상관 관계가 있다는
hdost

7
년, 월 및 일을로 단순화 할 수 있습니다 DATE(DT.[Date]).

@Keelan은 나를 위해 작동하지 않지만 CONVERT (date, DT. [Date])는 작동하지 않습니다.
Dan Parsonson

datepart(hour, workingPolicy.workingHours)/2.0제공 1.5하는 동안 datepart(hour, '1900-01-01 09:00:30.000')/2.0제공합니다 4.5. 왜 그런지 모르겠습니까? 참고 : workingPolicy.workingHours = 1900-01-01 09 : 00 : 30.000 . 도와주세요
affanBajwa

65

나는 파티에 늦었지만, 기존 답변에는 나타나지 않습니다.

GROUP BY DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', date_column) / 10 * 10, '2000')
  • 10MINUTE조건은 임의의 숫자로 변경 될 수 있습니다 DATEPART각각.
  • 이는 DATETIME 을 의미합니다.
    • 오랜 시간 간격으로 잘 작동합니다. (연도간에 충돌이 없습니다.)
    • SELECT명령문에 포함 시키면 출력이 지정한 레벨에서 잘린 출력 열이 제공됩니다.
  • '2000'SQL이 날짜 계산을 수행 할 "고정 날짜"입니다. Jereonh 0 최근 날짜를 초 또는 밀리 초 단위로 그룹화 할 때 이전 앵커 ( ) 에서 정수 오버플로가 발생한다는 것을 발견했습니다 .
SELECT   DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', aa.[date]) / 10 * 10, '2000')
                                                               AS [date_truncated],
         COUNT(*) AS [records_in_interval],
         AVG(aa.[value]) AS [average_value]
FROM     [friib].[dbo].[archive_analog] AS aa
GROUP BY DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', aa.[date]) / 10 * 10, '2000')
ORDER BY [date_truncated]

데이터가 수 세기에 걸쳐있는 경우 초 또는 밀리 초 그룹화에 단일 앵커 날짜를 사용하면 여전히 오버플로가 발생합니다. 이 경우 각 행에 비닝 비교를 해당 날짜의 자정에 고정하도록 요청할 수 있습니다.

  • 위에 나타난 곳 DATEADD(DAY, DATEDIFF(DAY, 0, aa.[date]), 0)대신에 사용하십시오 '2000'. 쿼리를 완전히 읽을 수는 없지만 작동합니다.

  • 대안이 대안이 될 수 있습니다 CONVERT(DATETIME, CONVERT(DATE, aa.[date])).

32 ≈ 4.29E + 9, 그래서 당신의 경우 DATEPARTIS SECOND, 당신은 양쪽에 43억초를 얻을, 또는 "앵커 ± 1백36년." 마찬가지로 2 32 밀리 초는 9.7 49.7 일입니다.
데이터가 실제로 수세기 또는 백만년에 걸쳐 있고 여전히 초 또는 밀리 초 까지 정확하다면… 축하합니다! 당신이 무엇을 하든지 계속하십시오.


특정 시작일부터이 작업을 수행 할 수 있습니까?
Pylander

1
@pylander는 물론입니다. where앞에 절을 넣으 십시오 group by.
마이클 - 클레이 셔키는 어디

2
내가 참조. / 20 * 2020 분 간격으로 데이터를 수집하는 것과 동일 하게 변경 하시겠습니까? 죄송합니다. 지금 수학에 어려움을 겪고 있습니다.
Lopsided 2016 년

2
DATEPART와 같은 SECOND의 경우 오류 메시지 ( The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.) 가 표시 됩니다. MINUTE는이 방법으로 사용할 수있는 가장 작은 날짜 부분 인 것 같습니다.
jeroenh

1
@ jeroenh, 맞습니다. 그것에 대해 이야기 할 섹션을 추가했습니다. tldr : 0'2000'(따옴표가 중요합니다!)로 변경하고 SECOND다시 시도 하십시오.
Michael-Clay Shirky의 위치

17

T-SQL에서는 다음을 수행 할 수 있습니다.

SELECT [Date]
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY [Date], DATEPART(hh, [Date])

또는

분 단위로 DATEPART(mi, [Date])

또는

10 분 사용 DATEPART(mi, [Date]) / 10(티모시가 제안한 것처럼)


1
GROUP BY [Date], DATEPART (hh, [Date])는 엉망입니다.
cnd

1
@nCdy 괜찮다. 그렇지 않으면 "... 선택 목록에 집계 함수 나 GROUP BY 절이 포함되어 있지 않기 때문에 선택 목록에 유효하지 않다"는 오류가 발생한다
tzup

1
전체 날짜와 시간별로 어떻게 그룹화합니까? Min Date 만 사용하고 있습니다.
cnd

Min (Date)을 사용하는 경우 물론 Group By에서 날짜를 가져올 수 있습니다.
tzup

3
분을 10으로 나눈 값은 10 분 간격으로 그룹화되어 필요한 것입니다. Modulo 10은 의미가 없습니다.
Tar

12

10 분 간격으로

GROUP BY (DATEPART(MINUTE, [Date]) / 10)

tzup과 Pieter888에서 이미 언급했듯이 한 시간 간격으로

GROUP BY DATEPART(HOUR, [Date])

2
그러나 여기서 나는 1980 년의 분을 2011 년의 분으로 그룹화합니다.
cnd

%가 올바른 수학일까요? 그것은 10 그룹을 만들지 않을 것입니다. 예를 들면 다음과 같습니다. 1 % 10 = 9 2 % 10 = 8 올바른 연대순 그룹 일 필요는 없습니다. 나는 정상적인 분열이 맞을 것이라고 생각합니다. %가 SQL에서 나머지 나누기가 아닌 한.
Steven

12
분을 10으로 나눈 값은 10 분 간격으로 그룹화되어 필요한 것입니다. Modulo 10은 의미가 없습니다.
Tar

타르와 동의 함. 그룹화는 의미가 없습니다.
MikeMurko

7

같은 것이어야합니다

select timeslot, count(*)  
from 
    (
    select datepart('hh', date) timeslot
    FROM [FRIIB].[dbo].[ArchiveAnalog]  
    ) 
group by timeslot

(구문에 대해 100 % 확신 할 수는 없습니다-저는 오라클에 더 가깝습니다)

Oracle에서 :

SELECT timeslot, COUNT(*) 
FROM
(  
    SELECT to_char(l_time, 'YYYY-MM-DD hh24') timeslot 
    FROM
    (
        SELECT l_time FROM mytab  
    )  
) GROUP BY timeslot 

6

저자가 작성한 원래의 대답은 꽤 잘 작동합니다. 이 아이디어를 확장하기 위해 다음과 같은 작업을 수행 할 수 있습니다

group by datediff(minute, 0, [Date])/10

60 분보다 긴 기간 (예 : 반나절 등 720)으로 그룹화 할 수 있습니다.


1
위의 MySQL 쿼리는 무엇입니까?
Biranchi

4

MySql의 경우 :

GROUP BY
DATE(`your_date_field`),
HOUR(`your_date_field`),
FLOOR( MINUTE(`your_date_field`) / 10);

1

내 해결책은 함수를 사용하여 날짜 간격으로 테이블을 만든 다음이 테이블을 날짜 간격을 사용하여 그룹화하려는 데이터에 조인하는 것입니다. 데이터를 표시 할 때 날짜 간격을 쉽게 선택할 수 있습니다.

CREATE FUNCTION [dbo].[fn_MinuteIntervals]
    (
      @startDate SMALLDATETIME ,
      @endDate SMALLDATETIME ,
      @interval INT = 1
    )
RETURNS @returnDates TABLE
    (
      [date] SMALLDATETIME PRIMARY KEY NOT NULL
    )
AS
    BEGIN
        DECLARE @counter SMALLDATETIME
        SET @counter = @startDate
        WHILE @counter <= @endDate
            BEGIN
                INSERT INTO @returnDates VALUES ( @counter )
                SET @counter = DATEADD(n, @interval, @counter)
            END
        RETURN
    END

1
declare @interval tinyint
set @interval = 30
select dateadd(minute,(datediff(minute,0,[DateInsert])/@interval)*@interval,0), sum(Value_Transaction)
from Transactions
group by dateadd(minute,(datediff(minute,0,[DateInsert])/@interval)*@interval,0)

8
stackoverflow에 오신 것을 환영합니다. 귀하는 귀하의 답변과 이것이 사이트에 이미있는 다른 10 개의 답변에 추가되는 내용을 충분히 설명해야합니다.
Simon.SA

0

SQL Server 2012의 경우 SQL Server 2008R2에서 작동한다고 생각하지만 다음 방법을 사용하여 시간을 밀리 초로 줄입니다.

DATEADD(MILLISECOND, -DATEDIFF(MILLISECOND, CAST(time AS DATE), time) % @msPerSlice, time)

이것은 다음에 의해 작동합니다.

  • 고정 점과 목표 시간 사이의 밀리 초 수 얻기 :
    @ms = DATEDIFF(MILLISECOND, CAST(time AS DATE), time)
  • 나머지 밀리 초를 시간 조각으로 나눕니다.
    @rms = @ms % @msPerSlice
  • 슬라이스 시간을 얻기 위해 나머지 시간의 음수를 목표 시간에 추가하십시오.
    DATEADD(MILLISECOND, -@rms, time)

불행히도, 이것은 마이크로 초와 더 작은 단위로 오버플로되므로 더 크고 더 미세한 데이터 세트는 덜 편리한 고정 소수점을 사용해야합니다.

나는 이것을 엄격하게 벤치마킹하지 않았고 빅 데이터가 아니므로 마일리지가 다를 수 있지만 장비 및 데이터 세트에서 시도한 다른 방법보다 성능이 눈에 띄게 나 빠지지 않았으며 임의의 슬라이싱에 대한 개발자 편의성에 대한 지불은 가치가 있습니다. 우리를 위해.


0
select from_unixtime( 600 * ( unix_timestamp( [Date] ) % 600 ) ) AS RecT, avg(Value)
from [FRIIB].[dbo].[ArchiveAnalog]
group by RecT
order by RecT;

두 600을 그룹화하려는 시간 (초)으로 바꿉니다.

이것을 자주 필요로하고 Archive라는 이름에서 알 수 있듯이 테이블이 변경되지 않으면 날짜 (& 시간)를 테이블에서 unixtime으로 변환하고 저장하는 것이 조금 더 빠를 것입니다.


0

나는 이것과 함께 공연에 늦었다는 것을 알고 있지만, 나는 이것을 사용했다-매우 간단한 접근법. 이를 통해 반올림 문제없이 60 분 슬라이스를 얻을 수 있습니다.

Select 
   CONCAT( 
            Format(endtime,'yyyy-MM-dd_HH:'),  
            LEFT(Format(endtime,'mm'),1),
            '0' 
          ) as [Time-Slice]

0
select dateadd(minute, datediff(minute, 0, Date), 0),
       sum(SnapShotValue)
FROM [FRIIB].[dbo].[ArchiveAnalog]
group by dateadd(minute, datediff(minute, 0, Date), 0)

1
질문에 답변 할 때 설명을 제공해주십시오.
Shizzen83
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.