mariadb 월별통계(없는 달은 0으로 표출) 질문드립니다. 0 3 1,852

by 포병이짱이여 [MySQL] [2022.02.02 01:57:20]


월별로 차트표출용 통계를 내야하는데 현재 있는 테이블로 어떤식으로 처리해야할지 1주일째 고민중입니다 ㅠㅠ..

A테이블

GP_ID(PK) GP_NM
1 서울
2 인천

 

B테이블

GA_ID(PK) GP_ID(FK) GA_NM
1 1 강남
2 1 강북
3 1 논현
4 2 미추홀

 

C테이블

SA_ID(PK) GA_ID(FK) SA_NM
1 1 입구
2 1 출구
3 2 입구
4 3 입구

 

D테이블

SP_ID(PK) SA_ID(FK) MEN WOMEN DATE
1 1 15 25 2022-01
2 1 10 20 2022-01
3 2 30 45 2022-02
4 3 50 60 2022-04
5 4 25 30 2022-03

 

위의 테이블처럼 존재합니다.

이때 검색조건을 GP_ID = 1, DATE(날짜)를 2022-01 ~ 2022-04월까지 검색한다고 하면

(GP_ID는 필수선택, GA_ID는 선택하거나 전체검색, 날짜설정 필수)

GA_ID DATE MEN WOMEN
1 2022-01 25 45
1 2022-02 30 45
1 2022-03 0 0
1 2022-04 0 0
2 2022-01 0 0
2 2022-02 0 0
2 2022-03 0 0
2 2022-04 50 60
3 2022-01 0 0
3 2022-02 0 0
3 2022-03 25 30
3 2022-04 0 0

 

위와 같은 형태로 결과가 표출되도록 작업을 하려고 합니다.

(MEN, WOMEN값은 동일한 GA_ID이면 합계로 표출이 되어야합니다)

선택한 날짜만큼 검색되려면 날짜데이터가 들어간 임시테이블이 필요하다고 해서 서브쿼리 형태로 출력시켜서 조인해봤는데

GA_ID가 제대로 표출이 안되서 막혔습니다.

도움을 받을 수 있을까요..

 

by 뉴비디비 [2022.02.02 21:54:17]
WITH Atbl (gp_id, gp_nm) AS (
	SELECT 1, '서울' UNION ALL 
	SELECT 2, '인천'
), Btbl (ga_id, gp_id, ga_nm) AS (
	SELECT 1, 1, '강남' UNION ALL 
	SELECT 2, 1, '강북' UNION ALL 
	SELECT 3, 1, '논현' UNION ALL 
	SELECT 4, 2, '미추홀'
), Ctbl (sa_id, ga_id, sa_nm) AS (
	SELECT 1, 1, '입구' UNION ALL 
	SELECT 2, 1, '출구' UNION ALL 
	SELECT 3, 2, '입구' UNION ALL 
	SELECT 4, 3, '입구' 
), Dtbl (sp_id, sa_id, men, women, date) AS (
	SELECT 1, 1, 15, 25, '2022-01' UNION ALL 
	SELECT 2, 1, 10, 20, '2022-01' UNION ALL 
	SELECT 3, 2, 30, 45, '2022-02' UNION ALL 
	SELECT 4, 3, 50, 60, '2022-04' UNION ALL 
	SELECT 5, 4, 25, 30, '2022-03' UNION ALL
	SELECT 6, 4, 27, 47, '2022-05'
)

-- 결과에 Atbl 항목이 없어서 쿼리에서 Atbl 없어도 되긴하지만, 참고 쿼리라서 테이블을 다 포함은 시켰어요.
SELECT 
	Btbl.ga_id, Dtbl.date 
	, SUM(CASE WHEN Dtbl.sa_id = Ctbl.sa_id THEN Dtbl.men   ELSE 0 END) men
	, SUM(CASE WHEN Dtbl.sa_id = Ctbl.sa_id THEN Dtbl.women ELSE 0 END) women
FROM Atbl 
	INNER JOIN Btbl ON Atbl.gp_id = Btbl.gp_id
	INNER JOIN Ctbl ON Btbl.ga_id = Ctbl.ga_id
	CROSS JOIN Dtbl
WHERE Atbl.gp_id = 1 AND Dtbl.date BETWEEN '2022-01' AND '2022-04' -- AND Btbl.ga_id = 2 
GROUP BY Btbl.ga_id, Dtbl.date 
ORDER BY Btbl.ga_id, Dtbl.date 

 


by 포병이짱이여 [2022.02.02 22:48:43]

와,,, 대박

어떻게 이렇게 깔끔하게 쿼리문이 표출이 되는지.....

진짜 정말 감사합니다ㅠㅠㅠㅠ

크로스조인 이런거 전혀 몰랐는데 꼭 다시 공부해서 머리속에 집어넣겠습니다!


by 마농 [2022.02.08 14:56:46]
WITH Atbl (gp_id, gp_nm) AS
(
SELECT 1, '서울' UNION ALL
SELECT 2, '인천'
)
, Btbl (ga_id, gp_id, ga_nm) AS
(
SELECT 1, 1, '강남' UNION ALL
SELECT 2, 1, '강북' UNION ALL
SELECT 3, 1, '논현' UNION ALL
SELECT 4, 2, '미추홀'
)
, Ctbl (sa_id, ga_id, sa_nm) AS
(
SELECT 1, 1, '입구' UNION ALL
SELECT 2, 1, '출구' UNION ALL
SELECT 3, 2, '입구' UNION ALL
SELECT 4, 3, '입구'
)
, Dtbl (sp_id, sa_id, men, women, date) AS
(
SELECT 1, 1, 15, 25, '2022-01' UNION ALL
SELECT 2, 1, 10, 20, '2022-01' UNION ALL
SELECT 3, 2, 30, 45, '2022-02' UNION ALL
SELECT 4, 3, 50, 60, '2022-04' UNION ALL
SELECT 5, 4, 25, 30, '2022-03' UNION ALL
SELECT 6, 4, 27, 47, '2022-05'
)
SELECT a.gp_id
     , a.gp_nm
     , b.ga_id
     , b.ga_nm
     , e.ym
     , IFNULL(SUM(d.men  ), 0) men
     , IFNULL(SUM(d.women), 0) women
  FROM Atbl a
 INNER JOIN Btbl b
    ON a.gp_id = b.gp_id
 CROSS JOIN
       (WITH RECURSIVE ym AS
        (
        SELECT '2022-01' ym
         UNION ALL
        SELECT DATE_FORMAT(DATE_ADD(CONCAT(ym, '-01'), INTERVAL 1 MONTH), '%Y-%m') ym
          FROM ym
         WHERE ym < '2022-04'
        )
        SELECT *
          FROM ym
       ) e
  LEFT OUTER JOIN Ctbl c
    ON b.ga_id = c.ga_id
  LEFT OUTER JOIN Dtbl d
    ON c.sa_id = d.sa_id
   AND e.ym = d.date
 WHERE a.gp_id = 1
 GROUP BY a.gp_id
     , a.gp_nm
     , b.ga_id
     , b.ga_nm
     , e.ym
;

 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입