2011-09-27 5 views
3

나는이 이와 같은 테이블 :이 테이블에서 시간 간격을 GROUP BY하는 방법이 있습니까?

DateTime A 

10:00:01 2 
10:00:07 4 
10:00:10 2 
10:00:17 1 
10:00:18 3 

이 나에게 각 십초 (A)의 평균 값을 반환하는 쿼리를 만들 수 있습니까? 이 경우 결과는 다음과 같습니다.

3 (4+2)/2 
2 (2+1+3)/3 

미리 감사드립니다.

편집 : 당신이 정말로 이것을 할 수 없다고 생각한다면 그냥 아무 말도하지 마라. :) 그것은 받아 들일 수있는 대답입니다,이 일을 할 수 있는지 정말로 모르겠습니다.

EDIT2 : SQL Server 2008을 사용하고 있습니다. 다른 그룹화를 원하지만 수정되었습니다. 예를 들어 10 초, 1 분, 1 분, 5 분, 30 분, 1 시간 및 1 일마다 범위를 지정할 수 있습니다 (예제 만 있지만 그와 비슷한 것).

+1

어떤 RDBMS를 사용하고 있습니까? 또한 단지'x0-x9'에서 고정 그룹을 원하십니까? 해당 그룹은 귀하의 데이터에 조건이 있습니까? –

+0

다른 그룹화를 원하지만 고정되어 있습니다. 예를 들어, 범위는 각각 10 초, 1 분, 5 분, 30 분, 1 시간 및 1 일입니다 (단지 예제 일뿐입니다) –

+0

귀하의 샘플 결과 수학은 입력 된 값과 일치하지 않습니다. 3은 설명에 있지만 입력 값에는 없습니다. – OCary

답변

4

을, 당신은 시간, 분, 초 정수 분할에 의해 DATEPART 다음 그룹을 사용할 수 있습니다 (10)

CREATE TABLE #times 
(
    thetime time, 
    A int 
) 

INSERT #times 
VALUES ('10:00:01', 2) 
INSERT #times 
VALUES ('10:00:07', 4) 
INSERT #times 
VALUES ('10:00:10', 2) 
INSERT #times 
VALUES ('10:00:17', 1) 
INSERT #times 
VALUES ('10:00:18', 3) 

SELECT avg(A) -- <-- here you might deal with precision issues if you need non-integer results. eg: (avg(a * 1.0) 
FROM #times 
GROUP BY datepart(hour, thetime), DATEPART(minute, thetime), DATEPART(SECOND, thetime)/10 

DROP TABLE #times 
+0

좋은 해결책 인 것 같습니다. 감사합니다! –

+0

현재이 방법을 사용하고 있습니다. 감사합니다 –

+1

1 일, 1 개월 또는 1 년 이상에 걸쳐있는 데이터를 수행하는 경우 해당 그룹에 절을 추가해야합니다. 그렇지 않으면 모든 1시, 2시, 3시 및 그래서 매일 같이 하나에 그룹화됩니다. GROUP BY 날짜 부분 (년, 시간), 날짜 부분 (월, 시간), 날짜 부분 (일, 시간), 날짜 부분 (시간, 시간), 날짜 부분 (분, 시간), 날짜 부분 (초, 시간)/10 – RyanfaeScotland

1

누군가가 전체 코드로 답을 줄 수 있지만 방법은 몇 가지 작은 문제/솔루션으로 그것을 무너 뜨리는 것입니다 접근 : 방법 :

(1) 간격으로 임시 테이블을 만듭니다. 이 질문에 허용 대답을 참조하십시오

Get a list of dates between two dates

이 답변은 MySQL을 위해,하지만 당신은 시작할 수 있습니다. 인터넷 검색 "간격 만들기 SQL"은이를 수행하는 추가 방법을 산출해야합니다. 메인 테이블의 MAX (DateTime) 및 MIN (DateTime)을 사용하는 방법에 상관없이 입력으로 사용할 수 있습니다 (스팬의 경우 10 초, 분명히).

(2) (의사)의 가입 조건, 기본 테이블과 임시 테이블에 참여하기 :

:

FROM mainTable m INNER JOIN #tempTable t ON m BETWEEN t.StartDate AND t.EndDate 

(3) 지금은만큼 제대로 선택 간단하고 그룹화해야한다

SELECT 
    AVG(m.A)  
FROM 
    mainTable m 
    INNER JOIN #tempTable t ON m BETWEEN t.StartDate AND t.EndDate 
GROUP BY 
    t.StartDate 

편집 : 더 레코드 (제로 평균)이없는 그와의 간격을보고 싶다면, 당신은 쿼리를 rearrage 왼쪽을 사용해야 가입하고 mA에 COALESCE 것 (아래 참조). 그러한 interals을 보는데 신경 쓰지 않는다면, OCary의 솔루션은 더 좋고/더 깨끗합니다.

SELECT 
    AVG(COALESCE(m.A, 0)) 
FROM 
    #tempTable t 
    LEFT JOIN mainTable m ON m BETWEEN t.StartDate AND t.EndDate 
GROUP BY 
    t.StartDate 
1

사용중인 DBMS에 따라 다릅니다. 오라클에서 다음 작업을 수행 할 수 있습니다 : SQL 서버에서

SELECT AVG(A) 
FROM MYTABLE 
GROUP BY to_char(DateTime, 'HH24:MI') 
+0

이것이 Oracle로 번역 될 수 있는지 알고 있습니까? –

+0

오라클 용입니다. –

1
CREATE TABLE IF NOT EXISTS `test` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `dtime` datetime NOT NULL, 
    `val` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 


INSERT INTO `test` (`id`, `dtime`, `val`) VALUES 
(1, '2011-09-27 18:36:19', 8), 
(2, '2011-09-27 18:36:21', 4), 
(3, '2011-09-27 18:36:27', 5), 
(4, '2011-09-27 18:36:35', 3), 
(5, '2011-09-27 18:36:37', 2); 

SELECT *, AVG(val) FROM test GROUP BY FLOOR(UNIX_TIMESTAMP(dtime)/10) 
+0

그것은 mysql이다, 미안하다, 나는 당신이 여기에서 두는 것보다 조금 일찍 그것을 썼다. – diNord

1

공통 테이블 표현식을 사용하여 데이터의 주어진 날짜 사이에 모든 마침표를 가져 와서이 문제에 접근했습니다. 원칙적으로 모든 SQL 간격으로 간격을 변경할 수 있습니다.

DECLARE @interval_minutes INT = 5, @start_date DATETIME = '20130201', @end_date DATETIME = GETDATE() 

;WITH cte_period AS 
(
    SELECT CAST(@start_date AS DATETIME) AS [date] 

    UNION ALL 

    SELECT DATEADD(MINUTE, @interval_minutes, cte_period.[date]) AS [date] 
    FROM cte_period 
    WHERE DATEADD(MINUTE, @interval_minutes, cte_period.[date]) < @end_date 
) 

, cte_intervals AS 
(SELECT [first].[date] AS [Start], [second].[date] AS [End] 
FROM cte_period [first] 
LEFT OUTER JOIN cte_period [second] ON DATEADD(MINUTE, 5, [first].[date]) = [second].[date] 
) 

SELECT i.[Start], AVG(data) 
FROM cte_intervals i 
LEFT OUTER JOIN your_data mu ON mu.your_date_time >= i.Start and mu.your_date_time < i.[End] 
GROUP BY i.[Start] 
OPTION (MAXRECURSION 0) 
+0

좋은 아이디어, 불행히도 프로젝트가 지금 종료되었습니다. 어쨌든 고마워, 나는 나중에 참조 할 수 있도록 그것을 예약했다. –

0

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=142634에서 당신은뿐만 아니라 다음 쿼리를 사용할 수 있습니다

select dateadd(minute, datediff(minute, 0, timestamp)/10 * 10, 0), avg (value) 
from yourtable 
group by dateadd(minute, datediff(minute, 0, timestamp)/10 * 10, 0) 
사람이 다음 제안에 따라 확장

:

Select 
a.MyDate, 
Start_of_10_Min = 
dateadd(mi,(datepart(mi,a.MyDate)/10)*10,dateadd(hh,datediff(hh,0,a.Mydate),0)) 
from 
(-- Test Data 
select MyDate = getdate() 
) a 

나는 그들이에 대한 계획도 어떻게 모르겠지만 두 번째 제안에서 평균을 얻는다.

개인적으로 나는 무엇이 거기에서 일어나고 있는지를 알고 있고 6 개월 후에 그것을 다시 보지 않고 그것을 이해할 수있을 것이라고 개인적으로 선호한다. 그러나 나는 이것을 완성하기 위해 이것을 포함한다.

관련 문제