인프런 워밍업 클럽 스터디 1기 BE 4번째 과제

인프런 워밍업 클럽 스터디 1기 BE 4번째 과제

문제1

과일 정보 저장 API

{
	"name": "사과",
	"warehousingDate": "2024-02-01",
	"price": 5000
}

위와 같은 정보를 받아서 저장할 수 있도록 fruit 테이블을 만들었다.

create table fruit (
	id bigint auto_increment,
  name varchar(30),
  warehousingdate date,
  price bigint,
  primary key(id)
);

그리고 이전에 구현했던 내용과 똑같이 INSERT문을 이용해 과일 정보 저장 API를 구현했다.

public void save(Fruit fruit) {
	String sql = "INSERT INTO fruit (name, warehousingdate, price) VALUES (?, ?, ?)";
	jdbcTemplate.update(sql, fruit.getName(), fruit.getWarehousingDate(), fruit.getPrice());
}

가격을 나타내는 price의 테이터 타입은 long을 사용했는데

int를 사용하지 않고 long을 사용하는 이유는

가격의 크기가 int의 범위를 초과할 수 있기 때문이다.

문제2

문제2는 과일이 팔린 경우 팔렸다는 정보를 저장하는 API를 구현하는 문제

팔렸다는 정보를 저장하기 위해서 fruit 테이블에 sold라는 컬럼을 추가했다.

create table fruit (
	id bigint auto_increment,
  name varchar(30),
  warehousingdate date,
  price bigint,
  sold boolean default false,
  primary key(id)
);

boolean 타입이고 default 값은 false인 sold 컬럼을 만들어서

과일이 팔린 경우 해당 API를 호출하면 sold 컬럼을 true로 바꿔주도록 구현헀다.

public void updateSold(Long id) {
	String sql = "UPDATE fruit SET sold = true WHERE id = ?";
	jdbcTemplate.update(sql, id);
}

문제3

특정 과일의 팔린 금액과 팔리지 않은 금액을 조회하는 API 구현하기

2가지의 방법으로 구현할 수 있다.

1. 과일의 이름에 해당하는 모든 데이터를 조회해서 Service 단에서 금액을 계산하기

FruitRepository

public List<Fruit> getStat(String name) {
	String sql = "SELECT name, price, sold FROM fruit WHERE name = ?";
	return jdbcTemplate.query(sql, (rs, rowNum) -> new Fruit(
		rs.getString("name"),
		rs.getLong("price"),
		rs.getBoolean("sold")
	), name);
}

FruitService

public FruitStatResponse getStat(String name) {
	List<Fruit> fruits = fruitRepository.getStat(name);
	long salesAmount = 0;
	long notSalesAmount = 0;
	for (Fruit fruit : fruits) {
		if (fruit.getSold()) {
			salesAmount += fruit.getPrice();
		} else {
			notSalesAmount += fruit.getPrice();
		}
	}
	return new FruitStatResponse(salesAmount, notSalesAmount);
}

데이터가 다음과 같이 들어있을 경우

image

원하는 결과를 조회할 수 있다.

image

2. 팔린 금액과 팔리지 않은 금액을 조회하는 쿼리를 만들기

public FruitStatResponse getStat(String name) {
	String sql = "SELECT SUM(CASE WHEN sold = true THEN price ELSE 0 END) salesamount, "
		+ "SUM(CASE WHEN sold = false THEN price ELSE 0 END) notsalesamount "
		+ "FROM fruit WHERE name = ?";
	return jdbcTemplate.queryForObject(sql, (rs, rowNum) -> new FruitStatResponse(
			rs.getLong("salesamount"),
			rs.getLong("notsalesamount")
		), name);
}

SUM 함수를 사용해서 금액의 합을 계산할 수 있고

CASE문을 사용하면 sold가 true인 금액을 조건으로 해서 계산할 수 있다.

 

이렇게 쿼리를 이용하면 다양한 조건의 데이터를 검색할 수 있기 때문에

Service단에서 원하는 데이터를 분류하는 작업을 하지 않을 수 있다.

SQL을 잘 알면 활용할 수 있는 방법이 무궁무진 하지만

SQL도 알면 알수록 더 어려워지는 것 같다…

댓글을 작성해보세요.