2013-07-10 3 views
1

사용자와 봇 (기본적으로 상태 시스템) 간의 모든 메시지를 저장하는 테이블이 있으며이 테이블의 모든 메시지/응답 쌍을 찾으려고합니다. , 각 사용자의 평균 응답 시간을 계산합니다. 주의해야 할 것은 모든 보내는 메시지가 응답을받는 것은 아닙니다.Postgres : 봇과의 상호 작용으로 인한 평균 사용자 응답 시간

각 행에는 message_id, user_id, created_at (timestamp), state_code 및 outgoing (boolean)이 저장됩니다.

나는 래그와 리드를 사용하여 메시지의 관련 쌍을 찾고 각 사용자에 대해 평균을 구한 created_at 값의 차이를 계산할 목적으로 창 함수를 살펴 보았습니다. 각 사용자의 평균을 제공합니다. 응답 시간. 이 문제는 두 메시지가 동일한 sate_code로 발행되었음을 보증 할 수있는 방법이 없다는 것입니다. 아이디어?

업데이트 : 사용자가 보낸 메시지가 동일한 상태 코드 인 경우 해당 메시지에 대한 응답임을 보증 할 수 있습니다. 그래서,이 경우에는 예

╔════════════╦═════════╦════════════╦════════════╦══════════╗ 
║ message_id ║ user_id ║ created_at ║ state_code ║ outgoing ║ 
╠════════════╬═════════╬════════════╬════════════╬══════════╣ 
║   1 ║  11 ║ mm/dd/yy ║   20 ║ t  ║ 
║   2 ║  11 ║ mm/dd/yy ║   20 ║ f  ║ 
║   3 ║  11 ║ mm/dd/yy ║   22 ║ t  ║ 
║   4 ║  11 ║ mm/dd/yy ║   21 ║ t  ║ 
║   5 ║  12 ║ mm/dd/yy ║   45 ║ t  ║ 
║   6 ║  12 ║ mm/dd/yy ║   46 ║ f  ║ 
║   7 ║  12 ║ mm/dd/yy ║   46 ║ t  ║ 
║   8 ║  12 ║ mm/dd/yy ║   20 ║ f  ║ 
║   9 ║  12 ║ mm/dd/yy ║   43 ║ t  ║ 
║   10 ║  13 ║ mm/dd/yy ║   20 ║ t  ║ 
╚════════════╩═════════╩════════════╩════════════╩══════════╝ 

위한 쌍, 그럼에도 불구하고, 사용자 1 보낸 메시지 만도 1 및도 2 물질이 상태 (20)로부터의 하나에 응답하는 메시지 (1)과 (2), 및 메시지 (6) 및 제 있다 상태 (20)

+0

관리를 위해 필요한 비즈니스 로직을 보여줍니다 몇 가지 예를 들어 데이터 나 의사 코드를 제공하기 위해 어떤 메시지가 관련이 있습니까? – MatBailie

+0

물론 더미 데이터를 추가했습니다! – avyfain

답변

2

내가 제대로 이해하고있는 동안 우리 보내는 메시지는 다음 outgoing이 거짓 때마다, 당신은 같은 user_idstate_code로 행을 이전에서 created_at을 원하는 받았다.

Windows 기능을 어떻게 사용할지 모르겠습니다. 여기에 상관 하위 쿼리를 사용하여 접근 방식은 다음과 같습니다

여기 하나의 방법입니다

select t.*, 
     (select created_at 
     from t t2 
     where t2.user_id = t.user_id and 
       t2.state_code = t.state_code and 
       t2.outgoing = 't' and 
       t2.created_at < t.created_at 
     order by t2.created_at desc 
     limit 1 
     ) as prev_created_at 
from t 

당신은 당신이 원하는 것을 얻을 수 있도록 날짜 연산을 수행 할 수 있습니다 (prev_created_at하지 NULL입니다 주로 있음).

당신은 이전 행이 "하나가 직전"당신이 lag()와 비슷한 뭔가를 할 수 있음을 알고있는 경우 :

select t.* 
from (select t.*, 
       lag(created_at) over (partition by user_id, state_code order by created_at) as prev_created_at, 
       lag(outgoing) over (partition by user_id, state_code order by created_at) as prev_outgoing 
     from t 
    ) t 
where t.outgoing = 'f' and t.prev_outgoing = 't'; 
+0

OVER 절에 ORDER BY가 필요하지 않습니까? – MatBailie

+0

@MatBailie. . . 분명히. 고맙습니다. –

+1

+1 - 모든 구석에 OP가 명확하지 않습니다. 나가는 상태 20 메시지와 들어오는 상태 20 메시지가 있지만 그 사이에 다른 메시지가있는 경우 모두 같은 사용자에 대해 여전히 쌍을 이루고 있습니까? 어느 쪽이든, 이것은 OP가 그 실제 요구 사항에 맞게 작동해야합니다 :) – MatBailie