안녕하세요 신입개발자입니다.
결과값 출력은 했지만 쿼리문이 깔끔하지 못한 것 같습니다 ㅠㅠ
중복되는 부분이 있거나 연산시간에 비효율적인 부분이 있는지,
더 좋은 방식으로 쿼리를 짤 수 없을지 조언을 얻고자 이렇게 글을 남기게 되었습니다.
이 쿼리문의 목적은
재활용쓰레기 [배출 장소 / 배출한 회원의 이름 / 쓰레기 수거 기기의 아이디]를 가져오기 위함입니다.
우선 종이테이블과 플라스틱테이블에 입력된 정보를 모두 가져오고자 UNION을 사용하였고
배출 장소, 회원 이름, 기기 아이디를 가져오기 위해
종이테이블과 플라스틱테이블 정보로는 얻을 수 없어
추가로 서브쿼리를 작성했습니다.
테이블 USERS (사용자 테이블) REGION (장소 테이블) EQUIPMENT (장비 테이블) WEIGHT (종이수거 테이블) COLLECTION_CNT (플라스틱 테이블) SELECT @ROWNUM := @ROWNUM + 1 ROWNUM , SUB.* FROM ( SELECT J_USR_ID userId ,J_EQUIPMENT_ID equipmentId ,J_WEIGHT_DTTM insertDttm ,J_WEIGHT weightNcnt ,PP_PAPER_PRICE price ,PP_POINT ecoPoint , ( SELECT DISTINCT ECO_REGION_ID FROM EQUIPMENT WHERE WEIGHT.J_EQUIPMENT_ID = EQUIPMENT.eco_equipment_id LIMIT 1 )regionArea /*+ 장소아이디를 가져오기위한 서브쿼리*/ , ( SELECT DISTINCT ECO_REGION_NM FROM REGION WHERE REGION.ECO_REGION_ID = regionArea LIMIT 1 )ecoRegionNm /*+ 장소아이디를 통해 장소명을 가져오기 위한 쿼리*/ , ( SELECT DISTINCT USER_NAME FROM USERS WHERE USERS.USER_ID=WEIGHT.J_USR_ID LIMIT 1 )userName /*+ 회원아이디로 회원 이름을 조회하기 위한 쿼리*/ , ( SELECT DISTINCT USER_GRADE FROM USERS WHERE USERS.USER_ID=WEIGHT.J_USR_ID LIMIT 1 )userGrade /*+ 회원아이디로 회원 등급을 조회하기 위한 쿼리*/ FROM WEIGHT WHERE 1=1 UNION SELECT ECHO_USR_ID userId ,ECHO_EQUIPMENT_ID equipmentId ,J_START_DTTM insertDttm ,J_CNT weightNcnt ,ECHO_PRICE price ,ECHO_POINT ecoPoint , ( SELECT DISTINCT ECO_REGION_ID FROM EQUIPMENT WHERE COLLECTION_CNT.ECHO_EQUIPMENT_ID = EQUIPMENT.ECO_EQUIPMENT_ID LIMIT 1 )regionArea /*+ 장소아이디를 가져오기위한 서브쿼리*/ , ( SELECT DISTINCT ECO_REGION_NM FROM REGION WHERE REGION.ECO_REGION_ID = regionArea LIMIT 1 )ecoRegionNm /*+ 장소아이디를 통해 장소명을 가져오기 위한 쿼리*/ , ( SELECT DISTINCT USER_NAME FROM USERS WHERE USERS.USER_ID=COLLECTION_CNT.ECHO_USR_ID LIMIT 1 )userName /*+ 회원아이디로 회원 이름을 조회하기 위한 쿼리*/ , ( SELECT DISTINCT USER_GRADE FROM USERS WHERE USERS.USER_ID=COLLECTION_CNT.ECHO_USR_ID LIMIT 1 )userGrade /*+ 회원아이디로 회원 등급을 조회하기 위한 쿼리*/ FROM COLLECTION_CNT, (SELECT @ROWNUM := 0) R ) SUB WHERE 1=1 ORDER BY insertDttm DESC
아래 사진은 결과값입니다
감사합니다 :)
1. 테이블이 정상적이라면
- Distinct 나 LIMIT 1 은 불필요 합니다.
- 서브쿼리 보다는 조인으로 풀어야 합니다.
- Union 이 아니라 Union All 을 사용해야 합니다.
2. DB 버전이 최신이라면 (MySQL 8.0 이상)
- @ROWNUM 보다는 ROW_NUMBER() 를 이용하는게 좋습니다.
SELECT ROW_NUMBER() OVER(ORDER BY a.insertDttm DESC) rn , a.userid , a.equipmentid , a.insertdttm , a.weightncnt , a.price , a.ecopoint , b.eco_region_id , c.eco_region_nm , d.user_name , d.user_grade FROM (SELECT j_usr_id userid , j_equipment_id equipmentid , j_weight_dttm insertdttm , j_weight weightncnt , pp_paper_price price , pp_point ecopoint FROM weight UNION ALL SELECT echo_usr_id userid , echo_equipment_id equipmentid , j_start_dttm insertdttm , j_cnt weightncnt , echo_price price , echo_point ecopoint FROM collection_cnt ) a INNER JOIN equipment b ON a.equipmentid = b.eco_equipment_id INNER JOIN region c ON b.eco_region_id = c.eco_region_id INNER JOIN users d ON a.userId = d.user_id ;