2016-06-14 2 views
1

에 대한 최소 값을 이전 n 번째 행을 선택 나는 내 출력은 행을 포함해야한다이하이브 : 열

ID START_DATE STATUS 
10 2013-05-29 FREE 
10 2013-05-29 PAID 
10 2014-05-30 PAID 
10 2014-11-29 FREE 
10 2014-12-02 PAID 
10 2015-09-29 PAID 
10 2015-12-02 PAID 
10 2016-04-04 PAID 
10 2016-04-05 FREE 

같은 데이터가 어디에 상태 = "무료". 상태가 FREE 일 때마다 Status = "PAID"인 이전 최소 날짜를 가져와야합니다.

ID STATUS PREVIOUS_MIN_PAID_START_DATE 
10 FREE NULL 
10 FREE 2013-05-29 
10 FREE 2014-12-02 

LAG() 기능은 첫 번째 이전 값을 제공, 내가 이전 최소 (n 번째) 값을 얻을 수있는 방법?

+0

원하는 출력이 명확하지 않다. 왜 행이 세 개인 이유는 무엇입니까? start_date 열이 없으므로 출력 행이 어느 입력 행과 일치하는지 명확하지 않습니다. – leftjoin

+0

원하는 출력 메시지를 업데이트했습니다. 이전에 연속 된 "유료"상태에서 이전 최소 시작 날짜를 가져 오려고합니다. 희망이 어떤 사람이 나를 도울 수 있습니다. – pshan99

+0

첫 번째 두 레코드의 날짜가 같습니다. 순서는 START_DATE뿐 아니라 STATUS에 따라 달라지며 예제 데이터의 버그입니까? – leftjoin

답변

0

내가 왜 downvotes를 받았는지 잘 모르겠다. 나는 이것이 꽤 흥미롭고 잘 설명 된 문제라고 생각했다. 어쨌든, 여기는 입니다.이 작업을 수행합니다.

기본적으로, 당신이 필요하면 (내가 올바르게 이해 한 희망) 다음 FREE에 도달 할 때까지 "현재"FREE 이후의 모든 PAID의 그룹을 생성하는 인덱스입니다. 설명하기 :

id start_date status idx 
10 2013-05-29 FREE 0 
10 2013-05-29 PAID 1 
10 2014-05-30 PAID 1 
10 2014-11-29 FREE 1 
10 2014-12-02 PAID 2 
10 2015-09-29 PAID 2 
10 2015-12-02 PAID 2 
10 2016-04-04 PAID 2 
10 2016-04-05 FREE 2 

을 그런 상태가 ID의 창을 새로 만든 인덱스를 통해 PAID 어디 최소 시작일을 얻을 수 있습니다 거기에서.

쿼리 :

WITH tmp_table AS (
    SELECT * 
    , SUM(flg) OVER (PARTITION BY id ROWS UNBOUNDED PRECEDING) AS s 
    FROM (
    SELECT * 
     , LEAD(CASE WHEN status='FREE' THEN 1 ELSE 0 END, 1, 0) OVER (PARTITION BY id) AS flg 
    FROM database.original_table) x) 

SELECT id 
    , status 
    , prev_date 
FROM (
    SELECT t.id, t.status, t.s, b.prev_date 
    FROM tmp_table t 
    LEFT OUTER JOIN (
    SELECT id, s, MIN(start_date) AS prev_date 
    FROM tmp_table 
    WHERE status='PAID' 
    GROUP BY id, s) b 
    ON b.id=t.id AND b.s=t.s) f 
WHERE status='FREE' 

출력 :

id status prev_date 
10 FREE NULL 
10 FREE 2013-05-29 
10 FREE 2014-12-02 
+0

OMG 이것은 최고입니다. 귀하의 솔루션은 완전히 작동합니다. 방금 테스트 했어. 엄청 고마워!!. – pshan99