⚙️백엔드 : Backend/DataBase
Raw SQL 쿼리를 Sequelize ORM 쿼리로 바꾸는 방법
예옹이
2024. 9. 14. 15:53
Raw SQL 쿼리를 활용해 원하는 레코드의 컬럼을 가지고 다양한 평균값을 내려고 했는데
동작이 안되더라고요! 그래서 Sequelize ORM 쿼리를 활용해 함수를 다시 만들었습니다
🤔 Sequelize ORM 쿼리를 활용해 만든 함수의 장점
- 간결하다
- 이해가 쉽다
- 유지보수가 쉽다
Raw SQL 쿼리를 사용한 코드
async getTeamAvg(team_id) {
try {
const result = await db.sequelize.query(
`SELECT
AVG(ac.job_requirement_score) AS team_job_req_avg,
AVG(ac.job_autonomy_score) AS team_job_auto_avg,
AVG(ac.relationship_conflict_score) AS team_rel_conf_avg,
AVG(ac.job_instability_score) AS team_job_inst_avg,
AVG(ac.organization_system_score) AS team_org_sys_avg,
AVG(ac.compensation_adequate_score) AS team_comp_ade_avg,
AVG(ac.job_culture_score) AS team_job_cul_avg,
AVG(ac.total_score) AS team_total_avg
FROM after_cares ac
JOIN users u ON ac.consultation_user_id = u.id
WHERE u.team_id = :team_id
AND YEAR(ac.examined_on) = YEAR(CURDATE());`,
{
replacements: { team_id },
type: db.sequelize.QueryTypes.SELECT,
raw: true // Ensure raw data without metadata
}
);
// Return the first result from the array
return result[0] || {}; // Return an empty object if no result
} catch (error) {
console.error("Error in getTeamAvg:", error);
throw error;
}
}
Sequelize ORM 쿼리를 사용한 코드
async getTeamAvg(team_id, year) {
const yearBetween = getStartAndEndYearWithoutTime(year);
try {
const result = await db.after_cares.findAll({
attributes: [
[db.sequelize.fn("AVG", db.sequelize.col("job_requirement_score")), "team_job_req_avg"],
[db.sequelize.fn("AVG", db.sequelize.col("job_autonomy_score")), "team_job_auto_avg"],
[db.sequelize.fn("AVG", db.sequelize.col("relationship_conflict_score")), "team_rel_conf_avg"],
[db.sequelize.fn("AVG", db.sequelize.col("job_instability_score")), "team_job_inst_avg"],
[db.sequelize.fn("AVG", db.sequelize.col("organization_system_score")), "team_org_sys_avg"],
[db.sequelize.fn("AVG", db.sequelize.col("compensation_adequate_score")), "team_comp_ade_avg"],
[db.sequelize.fn("AVG", db.sequelize.col("job_culture_score")), "team_job_cul_avg"],
[db.sequelize.fn("AVG", db.sequelize.col("total_score")), "team_total_avg"],
],
where: {
consultation_team_id: team_id,
examined_on: {
[Op.between]: [yearBetween.start, yearBetween.end],
},
},
raw: true,
});
return result[0] || {};
} catch (error) {
console.error("Error in getTeamAvg:", error);
throw error;
}
}
변환하는 방법
예 ) 변환할 Raw SQL 쿼리
SELECT AVG(ac.job_requirement_score) AS team_job_req_avg
FROM after_cares ac
JOIN users u ON ac.consultation_user_id = u.id
WHERE u.team_id = :team_id
AND YEAR(ac.examined_on) = YEAR(CURDATE());
-- 넘겨받은 team_id와 동일한 값을 가진 users 테이블의 사용자가 연결된 after_cares 데이터 중, examined_on의 연도가 현재 연도인 레코드의 job_requirement_score 평균을 계산하는 쿼리
Raw SQL 쿼리 변환하는 과정 (Step-by-Step)
(1) SELECT 구문을 attributes로 변환
SELECT에서 계산할 필드는 Sequelize에서 attributes 속성을 사용하여 지정한다
예를 들어, AVG(ac.job_requirement_score) 같은 SQL 구문은 sequelize.fn 함수를 사용하여 정의
attributes: [
[sequelize.fn('AVG', sequelize.col('job_requirement_score')), 'team_job_req_avg']
]
(2) JOIN 구문을 include로 변환
Sequelize ORM에서는 테이블을 조인할 때 include 옵션을 사용한다
JOIN users u ON ac.consultation_user_id = u.id 구문은 다음과 같이 변환
include: [{
model: Users,
where: { team_id: team_id }, // 조인 조건
attributes: [], // users 테이블에서 필요한 속성들
}]
(3) WHERE 절을 where 옵션으로 변환
WHERE 구문은 where 옵션으로 정의한다
특히 YEAR(CURDATE())와 같은 날짜 필터링은 Sequelize의 Op 연산자를 사용하여 처리할 수 있다
where: {
examined_on: {
[Op.between]: [startYear, endYear], // 년도를 특정 범위로 필터링
},
},
(4) 최종 코드
async function getTeamAvg(team_id) {
const year = new Date().getFullYear();
const { start, end } = getStartAndEndYearWithoutTime(year); // util에 있는 특정 년도의 시작과 끝 범위를 반환해주는 함수
try {
const result = await AfterCares.findAll({
attributes: [
[sequelize.fn('AVG', sequelize.col('job_requirement_score')), 'team_job_req_avg']
],
include: [{
model: Users,
where: { team_id: team_id }, // 조인 조건
attributes: [],
}],
where: {
examined_on: {
[Op.between]: [start, end], // 날짜 범위 필터링
},
},
raw: true,
});
return result;
} catch (error) {
console.error("Error in getTeamAvg:", error);
throw error;
}
}