주간 / 월간 / 연간 데이터 합계를 구하고자 한다고 가정해 보자.
예를 들면 일간 매출, 원가를 품목별로 구하려고 한다.
체크할 점은 어느 날에는 판매 이력이 있는 품목이 어느 날에는 없기도 하고 둘 다 존재하기도 한다는 점이다.
아래와 같이 검색 되는 테이블 데이터를
SELECT * FROM sales WHRE R_DATE='2012-12-15';
r_date | goods_nm | sales | cost |
2012-12-15 | 사과 | 50000 | 5000 |
2012-12-15 | 딸기 | 70000 | 6000 |
2012-12-15 | 레몬 | 5000 | 1600 |
SELECT * FROM sales WHRE R_DATE='2012-12-16';
r_date | goods_nm | sales | cost |
2012-12-16 | 사과 | 15000 | 300 |
2012-12-16 | 레몬 | 80000 | 5600 |
2012-12-16 | 망고 | 4500 | 100 |
이렇게 출력하고 싶은 경우
goods_nm | sales_15 | cost_15 | sales_16 | cost_16 |
사과 | 50000 | 5000 | 15000 | 300 |
딸기 | 70000 | 6000 | ||
레몬 | 5000 | 1600 | 80000 | 5600 |
망고 | 4500 | 100 |
여러 방법이 있겠지만 언어적으로 보면 두가지 방법이 있다.
MySQL 쿼리로 한번에 불러오는 방법과 PHP 코드 반복문으로 처리하는 방법.
두가지 경우를 모두 살펴 보자.
MySQL 쿼리를 사용하는 방법 (CASE WHEN)
SELECT tbl.goods_nm,
CASE WHEN tbl.r_date='15' THEN sales END AS sales_15,
CASE WHEN tbl.r_date='15' THEN cost END AS cost_15,
CASE WHEN tbl.r_date='16' THEN sales END AS sales_16
CASE WHEN tbl.r_date='16' THEN cost END AS cost_16
FROM (
SELECT '15' AS r_date, goods_nm, sales, cost FROM sales WHERE r_date='2012-12-15'
UNION
SELECT '16' AS r_date, goods_nm, sales, cost FROM sales WHERE r_date='2012-12-16'
) AS tbl
여기서 CASE WHEN 구문과 UNION 절에 사용된 구문을 늘리면 특정 기간, 주간 / 월간 단위로 데이터를 뽑아낼 수 있다.
PHP 코드로 구현하는 방법
DB SELECT 결과를 배열에 담았다고 가정하면 기간만큼 반복적으로 쿼리하는 방식으로 처리가 가능하다.
함수로 만든다면 아래와 같은 형태가 된다.
$result = array(); // 데이터를 합칠 변수 선언
for ($i = 15; $i < 17; $i++) {
$row = dbfunction($i); // 변수 $row 에 쿼리 결과를 반복적으로 담는다. 이 함수는 상황에 따라 만들자.
$result = data_monthly ($result, $row); // 이번 반복에서 $row 를 $result 에 추가한다
}
// 데이터를 배열에 집계하는 함수. 조금씩 수정하면 상황에 맞게 써먹을 수 있다.
function data_monthly ($target, $source) {
for ($i = 0; $i < count($source); $i++) {
$m = $source[$i]['r_date']; // 집계 결과물에서 column 명에 쓰일 날짜
$key = array_search($source[$i]['goods_nm'], array_column($target, 'goods_nm')); // 합칠 배열에서 품목명을 찾는다
if ($key !== false) {
// 찾았다면 해당 순서(index) 에 붙인다
$target[$key]['sales'.$m] = $source[$i]['sales'];
$target[$key]['cost'.$m] = $source[$i]['cost'];
} else {
// 새로운 품목이라면 index 자체를 추가한다.
$dummy = array(
'goods_nm' => $source[$i]['goods_nm'],
'sales'.$m => $source[$i]['sales'],
'cost'.$m => $source[$i]['cost'],
);
$target[] = $dummy;
}
}
return $target;
}
이 경우에 반복할 쿼리는 아래처럼 단순한 형태가 된다.
SELECT '15' AS r_date, goods_nm, sales, cost FROM tbl WHERE r_date='$date';
마치는 말
당연히 DB 쿼리로 한번에 데이터를 불러오는 방법이 성능적으로나 코드 간결화적으로나 우선시 되는 선택지이다.
하지만 아래와 같은 상황에 따라 일장일단이 있다.
- 어느 주기를 기준으로 데이터를 집계할 것인가 ex) 주간 / 월간 / 연간
- 하위 데이터를 산출하기에 테이블간 JOIN 이 얼마나 수월한가
- 중간 합계가 필요한가 GROUP BY ... WITH ROLLUP
WITH ROLLUP 으로 중간 합계를 구하고, 합계의 하위(자식 요소)로서 데이터를 구성하는 경우 PHP 코드로 구현한 방법이 더 수월하였다.
예시는 다른 포스팅에서 다루기로 하겠다.
'코딩 > SQL_Query' 카테고리의 다른 글
mysql - max / min group by 주의할 점 (0) | 2023.04.10 |
---|---|
MySQL - SELECT 결과로 UPDATE, JOIN 하여 UPDATE (0) | 2023.02.16 |
[MySQL] 초성 검색 함수 생성, 활용 (2) | 2022.10.04 |
mysql - 여러 행(row)의 데이터를 한 줄로 출력 (0) | 2022.09.28 |
[MySQL] 있으면 UPDATE 없으면 INSERT - ON DUPLICATE KEY UPDATE (0) | 2015.04.20 |