2017-12-15 1 views
3

테이블의 형식은 다음과 같습니다.날짜 값 테이블의 값을 기준으로 동일한 열에서

name  startdate       enddate 
******************************************************************** 
a  2017-03-08 00:13:00.000    2017-03-08 00:16:00.000 
a  2017-03-08 00:19:00.000    2017-03-08 00:21:00.000 

이 제발 도와주세요 다음과 같이

내가 SQL 쿼리를 사용하여 다음 테이블을 생성 할 필요가 위의 표에서
Id  name value  logdatetime 
************************************************* 
1  a  65   2017-03-08 00:13:00.000 
2  a  63   2017-03-08 00:14:00.000 
3  a  72   2017-03-08 00:15:00.000 
4  a  120  2017-03-08 00:16:00.000 
5  a  45   2017-03-08 00:17:00.000 
6  a  32   2017-03-08 00:18:00.000 
7  a  53   2017-03-08 00:19:00.000 
8  a  59   2017-03-08 00:20:00.000 
9  a  21   2017-03-08 00:21:00.000 

, 그것은 기본적으로 50보다 큰 값을 확인하고 데이터를 표시해야 이 쿼리에서

+0

시작일과 종료일이 어떻게 생성 되었습니까? – lucky

+0

어떻게 시작일과 종료일을 지정하고 있습니까? – Tomm

+0

나는 당신의 결과에'2017-03-08 00 : 21'이 틀렸다고 생각한다. 그리고 오른쪽은'2017-03-08 00 : 20'입니다. – Leran2002

답변

2

시도는 다음

CREATE TABLE #TestData(
    Id int, 
    name varchar(10), 
    value int, 
    logdatetime datetime 
) 

INSERT #TestData(Id,name,value,logdatetime)VALUES 
(1,'a',65,'2017-03-08 00:13:00.000'), 
(2,'a',63,'2017-03-08 00:14:00.000'), 
(3,'a',72,'2017-03-08 00:15:00.000'), 
(4,'a',120,'2017-03-08 00:16:00.000'), 
(5,'a',45,'2017-03-08 00:17:00.000'), -- separator 1 
(6,'a',32,'2017-03-08 00:18:00.000'), -- separator 2 
(7,'a',53,'2017-03-08 00:19:00.000'), 
(8,'a',59,'2017-03-08 00:20:00.000'), 
(9,'a',21,'2017-03-08 00:21:00.000') -- separator 3 


SELECT 
    name, 
    MIN(logdatetime) [start time], 
    MAX(logdatetime) [end time] 
FROM 
    (
    SELECT 
     *, 
     SUM(IsSeparator)OVER(
          PARTITION BY name 
          ORDER BY logdatetime,Id 
          ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 
         ) SeparatorCount 
    FROM 
     (
     SELECT 
      *, 
      --IIF(value<=50,1,0) IsSeparator -- it's a special marker 
      CASE WHEN value<=50 THEN 1 ELSE 0 END IsSeparator -- you can use CASE instead IIF 
     FROM #TestData 
    ) q 
) q 
WHERE value>50 -- exclude values less 50 
GROUP BY name,SeparatorCount -- use SeparatorCount here 

DROP TABLE #TestData 

내가 SQLServer 2014에 테스트를 사용할 수 있습니다.

SQL 바이올린 - 당신은 재귀 CTE

;WITH numCTE AS(
    SELECT *,ROW_NUMBER()OVER(PARTITION BY name ORDER BY logdatetime,Id) n 
    FROM #TestData 
), 
groupCTE AS(
    SELECT name,logdatetime,value,n,1 groupNum 
    FROM numCTE 
    WHERE n=1 

    UNION ALL 

    SELECT n.name,n.logdatetime,n.value,n.n, 
    --g.groupNum+IIF(n.value<=50,1,0) 
    g.groupNum+CASE WHEN n.value<=50 THEN 1 ELSE 0 END 
    FROM numCTE n 
    JOIN groupCTE g ON n.name=g.name AND n.n=g.n+1 
) 
SELECT 
    name, 
    MIN(logdatetime) [start time], 
    MAX(logdatetime) [end time] 
FROM groupCTE 
WHERE value>50 
GROUP BY name,groupNum 

과 다른 변형을 사용할 수 있습니다 http://sqlfiddle.com/#!6/ff80e/1

또는 그러나 나는 첫 번째 변종이 더 나은 생각합니다.

다른 변형입니다. 첫 번째 변형보다 짧습니다.

SELECT 
    name, 
    MIN(logdatetime) [start time], 
    MAX(logdatetime) [end time] 
FROM 
    (
    SELECT 
     *, 
     SUM(CASE WHEN value<=50 THEN 1 ELSE 0 END)OVER(
       PARTITION BY name 
       ORDER BY logdatetime,Id 
       ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 
      ) groupNum 
    FROM #TestData 
) q 
WHERE value>50 
GROUP BY name,groupNum 
+0

고맙습니다. Leran, 그 작업 ... – ramakrishna

0
;with CTE AS(select *,CASE WHEN VALue>50 then 1 else 0 end AS cnt from #TestData) 
    select DISTINCT Name, 
       case when nullif(cnt,lag(Cnt)over(order by logdatetime))=1 then logdatetime end StartDATE, 
       case when nullif(cnt,lead(Cnt)over(order by logdatetime))=1 then logdatetime end ENDDATE 
       from CTE 
+0

이것은 원하는 출력이되지 않을 것입니다. – Tomm

+0

우리는 OP의 응답을 기다려야합니다. –

+0

시작 날짜가 처음 식별 된 초과 된 값 레코드의 logdatetime이되고 종료 날짜가 마지막으로 식별 된 초과 된 값 레코드의 logdatetime이됩니다. 각 레코드의 시간 간격은 1 분이 될 것이기 때문에 레코드 순서에서만 찾을 수 있습니다. 그런 다음 다음 초과 된 값 레코드가 다시 시작 날짜가되며, 마지막으로 초과 된 값 레코드는 종료 날짜가됩니다. 더 이상 혼란스러워하지 않았 으면 좋겠다. – ramakrishna

관련 문제