-
4개의 with절과 union all을 사용해서 집계 결과 만들기Backend/SQL(Mariadb_ver) 및 DB 2024. 2. 4. 16:36
필자는 이 전에 다루었던 union all의 원리를 이용해서, with절 여러개를 만들어 하나의 결과로 만드는 쿼리를 만들었다.
그 전에 다루었던 공통 테이블식을 사용하였고, 테이블은 다르지만 지정된 구역의 값의 개수를 count하여 집계하여 보는 것이 나의 목표였다.
<필요한 조건>
1. 현재 날짜, 시간 기준이다.
2. 이상치 혹은 결측치에 대한 값을 집계한다.
3. 만약 이 구역에서 집계된 부분이 0 이면 0으로 결과값이 나타나도록 한다.
위를 만족하는 쿼리를 만들기 위해 5번 정도(?) 수정이 필요했지만, 결국에는 완성되었다.
완성된 쿼리는 아래를 참고하자.
WITH all_combinations_alarm AS ( SELECT DISTINCT region, null as area, con_type FROM test.hogen_batch_table WHERE region = 'edu1_5' ), total_alarm AS ( SELECT ac.region, null as area, COALESCE(subquery.save_dt, '') as save_dt, ac.con_type, COALESCE(SUM(subquery.cnt), 0) as cnt, 'hogen' as data_type FROM all_combinations_alarm ac LEFT JOIN ( SELECT save_dt, region, null as area, con_type, (COUNT(CASE WHEN alarm = 'null_value' THEN 1 ELSE NULL END) + COUNT(CASE WHEN alarm IN ('under', 'over') THEN 1 ELSE NULL END)) as cnt FROM test.hogen_batch_table WHERE substr(save_dt, 1, 10) = CURRENT_DATE() AND substr(save_dt, 12, 2) = DATE_FORMAT(now(), '%H') AND (con_type = 'hogen_inside' OR con_type = 'hogen_control') AND substr(save_dt, 15, 1) = "1" -- DATE_FORMAT(now(), '%m')" AND region = 'edu1_5' GROUP BY 1, 2, 3 ) subquery ON ac.region = subquery.region AND ac.con_type = subquery.con_type GROUP BY 1, 2, 3 ), all_combinations_conditioner AS ( SELECT DISTINCT region, area FROM test.conditioner_batch_table WHERE region = 'mylease1' AND area = '2' ), total_conditioner AS ( SELECT ac.region, ac.area, COALESCE(subquery.save_dt, '') as save_dt, COALESCE(subquery.con_type, 'total') as con_type, COALESCE(SUM(subquery.cnt), 0) as cnt, 'conditioner' as data_type FROM all_combinations_conditioner ac LEFT JOIN ( SELECT save_dt, region, area, con_type, (COUNT(CASE WHEN alarm = 'null_value' THEN 1 ELSE NULL END) + COUNT(CASE WHEN alarm IN ('under', 'over') THEN 1 ELSE NULL END)) as cnt FROM test.conditioner_batch_table WHERE substr(save_dt, 1, 10) = CURRENT_DATE() AND substr(save_dt, 12, 2) = DATE_FORMAT(now(), '%H') AND substr(save_dt, 15, 1) = "2" -- DATE_FORMAT(now(), '%m')" AND region = 'mylease1' AND area = '2' GROUP BY 1, 2, 3, 4 ) subquery ON ac.region = subquery.region AND ac.area = subquery.area GROUP BY 1, 2, 3, 4 ) SELECT * FROM total_alarm UNION ALL SELECT * FROM total_conditioner;
<간략한 설명을 하자면>
1. all 로 시작하는 with 절의 경우, 각각 테이블(아래)에 지역, 구역별 필터링을 적용하기 위해서 넣었다.
그리고 union을 하는 경우 꼭 컬럼의 개수를 맞춰줘야 하기 때문에 area 가 없는 테이블의 경우 null로 채워준다.
2. total로 시작하는 with절의 경우
- 서브쿼리에서 날짜, 시간, 필요한 region, area 구역에 따라 count 집계 값을 나타낸다
- 서브쿼리를 바탕으로 COALESCE 함수를 사용하여 집계가 0 이어도, 날짜, 구역의 값이 나오도록 해준다.
3. 위 4개의 with 절을 사용하여, union all 을 하면 아래와 같이 결과가 나온다.
cnt 값이 0 이어도 모든 region, area가 나올 수 있도록 완성하였다.
필자의 경우, 날짜를 API에서 다시 처리하기 때문에 비워두었지만, row 데이터가 필요하다면, 가공하지 않아도 괜찮다.
'Backend > SQL(Mariadb_ver) 및 DB' 카테고리의 다른 글
MariaDB 에서 함수 생성하기 - sql 함수 생성 및 적용 방법 (1) 2024.02.14 Union ALL 사용하여 테이블 2개 결과값 한번에 보여주기 (0) 2024.02.04 DB 설계 - 3. 논리적 설계 (0) 2024.01.23 DB 설계 - 2.개념적 설계 (0) 2024.01.12 DB 설계 - 1. 요구 사항 수집 분석 (1) 2024.01.11