MySQL 리트코드 | Average Time of Process per Machine

    728x90

     

    문제

    https://leetcode.com/problems/average-time-of-process-per-machine/?envType=study-plan-v2&envId=top-sql-50

    • machine 별 프로세스 평균 시간 구하기
    • 프로세스 완료 시간은 activity_type이 'end'인 timestamp에서 'start'인 timestamp를 빼면 됨.
    • 결과는 소수점 셋째자리로 표현하기

     

    테이블

    Activity machine_id process_id activity_type timestamp
    0 0 start 0.712
    0 0 end 1.520
    0 1 start 3.140
    0 1 end 4.120
    1 0 start 0.550
    1 0 end 1.550
    1 1 start 0.430
    1 1 end 1.420
    2 0 start 4.100
    2 0 end 4.512
    2 1 start 2.500
    2 1 end 5.000
    • machine_id 별로 processing_time 구하기
    • processing_time은 한 기계(machine_id) 당 process_id 별 (end 시간 - start 시간)의 평균  

     

    풀이과정

    # 튜플 형식으로 셀프조인, activity_type이 다른 경우 조인

    • 한 기계 당 여러 프로세스들이 돌아가고 있음. 기계 별로 프로세스들의 평균 러닝타임을 구해야 함.
      • 평균 러닝타임 = 기계 별 프로세스 별 ( '마감' 시간 -  '시작' 시간)의 평균 
    • 프로세스 별로 '마감'시간과 '시작' 시간을 한 행으로 보기 위해 셀프 조인을 해줌 
    • 조인 조건은 ① machine_id와 process_id가 같은 경우에, ② activiy_type이 다른 경우('end', 'start')에만 조인되도록 설정 
      • 같은 machine_id와 process_id를 가지고 있으면서,
        activity_type이 'start'인 경우에는 'end'인 경우의 데이터가 추가되고,
        activity_type이 'end'인 경우에는 'start'인 경우의 데이터가 추가됨.
        → (셀프 코드 피드백) 메모리를 비효율적으로 사용하고 있음.
             하나의 machine_id와 process_id 별 start 시간과 end 시간을 표현할 때 두 행을 사용하고 있음.  

    조인 조건에 activity_type이 같지 않을 때 조인되도록 설정하면 한 기계와 프로세스 당 (같은 정보를 담은) 두 행의 데이터가 생성됨.

     

    # 정답

    • SELECT 문으로 machine_id와 activity_type 간 차이의 절댓값의 평균을 계산한 processing_time을 조회해주기
      • 상단 풀이과정에서 서술했듯,
        같은 machine_id와 process_id 별로 activity_type이 다른 경우에 셀프 조인이 된 상태이기 때문에
        두 activity_type 데이터를 빼면 한 행은 +값이 나오고, 다른 행은 -값이 나오게 됨.

    그렇기 때문에 ABS() 절댓값 함수를 사용함.

    • activity_type이 다른 경우, 두 값을 빼고 절댓값을 취해줌. 그 후 평균을 구하고, ROUND 함수로 소수점 자리를 맞춰줌.
      → 다행히 평균을 구하는 문제였기 때문에 여기에서 절댓값들을 더한 뒤 1/N 했을 때 정답이 나오게 된 것. 
    • 한 기계 당 프로세스 평균 러닝타임을 구하기 위해서는 machine_id로 GROUP BY 해야 함.
    1
    2
    3
    4
    5
    SELECT a1.machine_id, ROUND(AVG(ABS(a1.timestamp-a2.timestamp)),3) processing_time
    FROM Activity a1
    JOIN Activity a2 ON (a1.machine_id, a1.process_id) = (a2.machine_id, a2.process_id)
    AND a1.activity_type != a2.activity_type
    GROUP BY a1.machine_id
    cs

     

     

    다른 사람 풀이

    # 튜플 형식으로 셀프조인, activity_type을 지정해서 조인

    • 프로세스 별로 '마감'시간과 '시작' 시간을 한 행으로 보기 위해 셀프 조인을 해줌 
    • 조인 조건은 ① machine_id와 process_id가 같은 경우에, ② 왼쪽 테이블은 activity_type이 'start'이고, ③ 오른쪽 테이블은 activity_type이 'end'인 경우에 조인되도록 설정
      • 같은 machine_id와 process_id를 가지고 있으면서,
        왼쪽 테이블의 activity_type은 'start'이면서 오른쪽 테이블의 activity_type이 'end'일 때 데이터가 추가됨.
        한 machine_id와 process_id 별 시작(start)과 마감(end) 시간이 한 행에 나옴. 
    • 두 timestamp 값의 차이를 구한 뒤 평균을 구하고, ROUND 함수로 소수점 자리를 맞춰줌.
    • 한 기계 당 프로세스 평균 러닝타임을 구하기 위해서는 machine_id로 GROUP BY 해야 함.
    1
    2
    3
    4
    5
    SELECT a1.machine_id, ROUND(AVG(a2.timestamp - a1.timestamp), 3) processing_time
    FROM Activity a1
    JOIN Activity a2 ON (a1.machine_id, a1.process_id) = (a2.machine_id, a2.process_id)
    AND a1.activity_type = 'start' AND a2.activity_type = 'end'
    GROUP BY a1.machine_id
    cs

     

     

     

    728x90

    댓글