오늘은 SQL에서 SUM, AVG, COUNT, MIN, MAX를 사용해 데이터의 합계와 평균, 개수, 최솟값과 최댓값을 구하는 방법을 배웠다.
처음에는 이런 계산은 엑셀에서 해야 한다고 생각했다. 하지만 SQL을 사용하면 데이터베이스에 저장된 많은 데이터를 따로 옮기지 않고도 한 번에 계산할 수 있었다.
또 WHERE로 필요한 데이터만 선택하고, GROUP BY로 같은 종류의 데이터를 묶은 뒤, ORDER BY로 원하는 순서대로 정렬할 수 있다는 것도 알게 되었다.
오늘 배운 내용을 한 문장으로 정리하면 다음과 같다.
SQL은 데이터를 단순히 조회하는 것뿐만 아니라, 필요한 조건으로 나누고 계산해 원하는 결과를 만드는 데 사용할 수 있다.
SQL에서도 더하기, 빼기, 곱하기, 나누기 연산을 사용할 수 있다.
연산자 의미
+ 더하기
- 빼기
* 곱하기
/ 나누기
예를 들어 음식 준비 시간과 배달 시간을 더해 전체 소요 시간을 구할 수 있다.
SELECT food_preparation_time,
delivery_time,
food_preparation_time + delivery_time AS total_time
FROM food_orders
이 쿼리는 각 주문의 음식 준비 시간과 배달 시간을 보여주고, 두 값을 더한 결과를 total_time이라는 이름으로 함께 보여준다.
여러 행의 데이터를 하나의 결과로 계산할 때 집계 함수를 사용할 수 있다.
함수 역할
SUM() 합계
AVG() 평균
COUNT() 개수
MIN() 최솟값
MAX() 최댓값
음식 준비 시간의 총합과 평균 배달 시간을 구하는 쿼리다.
SELECT SUM(food_preparation_time) AS total_food_preparation_time,
AVG(delivery_time) AS avg_food_delivery_time
FROM food_orders
엑셀에서는 계산할 셀의 범위를 지정하지만, SQL에서는 계산할 컬럼을 함수 안에 넣는다는 차이가 있었다.
SELECT COUNT(*) AS count_of_orders,
COUNT(DISTINCT customer_id) AS count_of_customers
FROM food_orders
COUNT(*)는 전체 주문 행의 개수를 구한다.
전체 주문 수와 실제로 주문한 고객 수는 서로 다를 수 있다. 한 명의 고객이 여러 번 주문할 수 있기 때문이다.
DISTINCT를 사용하면 중복된 고객 ID를 하나로 처리하기 때문에, 실제로 주문한 고객이 몇 명인지 구할 수 있다.
SELECT MIN(price) AS min_price,
MAX(price) AS max_price
FROM food_orders
MIN()은 가장 작은 주문 금액을, MAX()는 가장 큰 주문 금액을 구한다.
집계 함수만 사용하면 테이블의 전체 데이터를 계산한다. 특정 조건에 맞는 데이터만 계산하려면 WHERE를 함께 사용해야 한다.
예를 들어 30,000원 이상인 주문이 몇 건인지 구하려면 다음과 같이 작성한다.
SELECT COUNT(*) AS count_of_orders
FROM food_orders
WHERE price >= 30000;
이 쿼리를 작성하기 전에는 다음 순서로 필요한 내용을 먼저 정리했다.
위 문제에 적용하면 다음과 같다.
테이블: food_orders
필요한 컬럼: price
조건: price >= 30000
계산: COUNT(*)
처음부터 SQL 문법을 바로 작성하려고 하면 어떤 구문을 사용해야 할지 헷갈렸다. 먼저 필요한 내용을 말로 나눈 뒤 SQL로 옮기니 조금 더 쉽게 작성할 수 있었다.
한국 음식의 평균 주문 금액도 같은 방식으로 구할 수 있다.
SELECT AVG(price) AS average_price
FROM food_orders
WHERE cuisine_type = 'Korean'
WHERE는 조건에 맞는 데이터만 선택할 때 사용한다. 하지만 모든 음식 종류의 주문 금액을 각각 계산하려면 음식 종류마다 쿼리를 반복해서 작성해야 한다.
이때 GROUP BY를 사용하면 원하는 기준으로 데이터를 묶어 한 번에 계산할 수 있다.
SELECT cuisine_type,
SUM(price) AS sum_of_price
FROM food_orders
GROUP BY cuisine_type
위 쿼리는 주문 데이터를 음식 종류별로 묶은 뒤, 각 음식 종류의 주문 금액 합계를 계산한다.
음식점별 최고 주문 금액도 같은 방식으로 구할 수 있다.
SELECT restaurant_name,
MAX(price) AS max_price
FROM food_orders
GROUP BY restaurant_name
처음에는 WHERE와 GROUP BY의 차이가 헷갈렸다. 지금은 다음과 같이 이해했다.
ORDER BY는 조회한 결과를 원하는 순서대로 정렬할 때 사용한다.
음식점별 최고 주문 금액을 구하고, 금액이 큰 순서로 정렬하면 다음과 같다.
SELECT restaurant_name,
MAX(price) AS max_price
FROM food_orders
GROUP BY restaurant_name
ORDER BY max_price DESC
이 쿼리에는 오늘 배운 내용이 다음 순서로 함께 사용됐다.
각 구문을 따로 배울 때보다 하나의 쿼리 안에서 연결해보니 역할이 조금 더 잘 보였다.
강의 코드를 복사했는데 실행되지 않았다
강의에 있는 코드를 그대로 복사했는데 SQL이 실행되지 않는 문제가 있었다.
코드가 눈으로 보기에는 똑같아 보여서 처음에는 함수나 문법을 잘못 사용한 줄 알았다. 하지만 복사하는 과정에서 일반 공백이 아닌 특수한 공백이 포함되면 오류가 발생할 수 있다는 것을 알게 되었다.
문제가 발생한 부분을 지우고 직접 다시 입력하자 정상적으로 실행됐다.
앞으로 강의 코드를 복사했는데 이유 없이 오류가 발생한다면 다음 내용을 확인해봐야겠다.
고객 수를 구하는 쿼리를 작성하면서 customer_id를 cutomer_id로 잘못 입력한 적도 있었다.
-- 잘못 입력한 컬럼명
cutomer_id
-- 올바른 컬럼명
customer_id
SQL은 내가 의도한 단어를 추측하지 않고 정확한 컬럼명을 사용한다. 코드가 짧더라도 철자 하나가 다르면 실행되지 않을 수 있기 때문에 오류가 발생하면 컬럼명부터 확인해야 한다는 것을 배웠다.
지금은 준비된 주문 데이터에서 값을 검색하고 계산하는 방법을 배운 것 같다. 하지만 실제 백엔드 서비스에서 SQL이 어디서 호출되고, 계산한 결과가 사용자 화면에 어떻게 전달되는지는 아직 배우지 않았다.
그래서 오늘 배운 내용을 내가 생각했던 매장 마감보고 관리 서비스에 대입해보았다.
예를 들어 결제 방식별 매출을 구한다면 다음과 같은 형태가 될 것 같다.
SELECT pay_type,
SUM(price) AS total_price
FROM payments
GROUP BY pay_type
ORDER BY total_price DESC
아직 내가 직접 서비스에 연결해본 것은 아니지만, 백엔드 서버가 데이터베이스에 SQL을 보내 결과를 받아오고, 그 결과를 관리자 화면이나 마감보고에 보여주는 흐름이 아닐까 생각했다.
앞으로 Java와 Spring을 배우면서 SQL로 조회한 데이터가 실제 서비스 화면까지 어떤 과정을 거쳐 전달되는지 확인해보고 싶다.
오늘은 강의 제목처럼 엑셀을 사용하지 않고도 SQL에서 필요한 값을 한 번에 계산하는 방법을 배웠다.
데이터가 적을 때는 엑셀로도 직접 계산할 수 있지만, 데이터가 많아지면 조건에 맞는 값을 찾고 종류별로 나누는 일이 복잡해질 것 같다. SQL에서는 WHERE, GROUP BY, 집계 함수를 조합해 원하는 결과를 한 번에 구할 수 있다는 점이 신기했다.
아직은 이미 만들어진 테이블에서 데이터를 검색하고 계산하는 방법을 배운 단계다. 내가 작성한 SQL이 실제 백엔드 서비스의 어느 부분에서 실행되고, 조회 결과가 사용자에게 어떻게 보여지는지는 아직 잘 모르겠다.
지금 배운 문법이 나중에 Java와 Spring, 데이터베이스와 어떻게 연결될지 궁금하다. 앞으로 더 많은 내용을 배우면서 오늘 작성한 짧은 쿼리가 실제 서비스의 기능이 되는 과정까지 이해해보고 싶다.