안녕하세요. 저는 Node.js + MySQL(Cloud SQL) 환경에서 개발하고 있는 개발자입니다. SELECT 문을 사용해서 데이터를 뽑아오려고 하는데, 시간이 너무 오래걸려서 고수님들의 도움이 필요합니다.
테이블 먼저 말씀드리겠습니다.
-product
code | int(10) | PK |
name | varchar(30) | NOT NULL |
register_date | datetime | NOT NULL |
-label
code | int(10) | PK |
content | varchar(10) | NOT NULL |
-product_and_label
product_code | int(10) | PK |
label_code | int(10) | PK |
하나의 상품(product)이 여러개의 라벨(label)을 가질 수 있고 상품과 라벨의 관계는 product_and_label 테이블을 통해 나타내었습니다.
여러개의 상품 리스트를 가져와야하는 상황인데, 저는 Node.js 에서 아래와 같은 로직으로 데이터를 가져오고있습니다.
1. "SELECT name, register_date FROM product" 쿼리문을 통해 product 를 전부 가져온다.
2. for 문을 사용하여 모든 상품을 탐색하며 상품에 해당하는 라벨들을 가져온다.
간단한 코드로 표현하자면
product = connection.query("SELECT code, name, register_date FROM product")
for(let i = 0; i < product.length; i++){
product[i].label = connection.query("SELECT label.code, label.content FROM product_and_label LEFT JOIN label ON product_and_label.label_code = label.code WHERE product_and_label.product_code = product[i].code");
}
return product;
이런 식으로 상품 리스트 데이터를 정상적으로 반환하지만 200개가 되지 않는 상품을 가져오는데 16-18초 정도 소요됩니다. ㅠㅠ 시간을 줄일 수 있는 쿼리문이나 개발 아이디어 있으시면 도움 부탁드립니다.
정리하자면
1. for문을 사용하지 않고 라벨을 가져오는 방법이 있는지 ?
2. 로직은 맞지만 데이터 베이스 설정값 ??등에 문제가 있어서 성능이 안나오는건지
고수님들의 의견 기다리겠습니다.
읽어주셔서 감사합니다.
두번째 쿼리에서 처럼 조인쿼리를 사용하시면 됩니다.
단, 특정 상품코드 조건을 빼고, 전체 조회로 하시면 됩니다.
SELECT b.product_code , a.name product_name , a.register_date , b.label_code , c.content label_content FROM product a INNER JOIN product_and_label b ON a.code = b.product_code INNER JOIN label c ON b.label_code = c.code ORDER BY b.product_code, b.label_code ;
미농님 친절한 답변 감사합니다. 미농님께서 작성해주신 쿼리문을 실행하게 된다면 아래와 같은 row가 추출될 것이라고 예상됩니다.
product_code | product_name | register_date | label_code | label_content |
1 | 의자 | 1/1 | 1 | 세일상품 |
1 | 의자 | 1/1 | 2 | 인기상품 |
1 | 의자 | 1/1 | 3 | 세트상품 |
1 | 의자 | 1/1 | 4 | 품절임박 |
2 | 책상 | 1/2 | 1 | 세일상품 |
2 | 책상 | 1/2 | 2 | 인기상품 |
위와 같은 데이터는 product의 colum 수가 많아지고, product가 가지고 있는 label 의 수가 많아질수록 중복되는 product data가 많아집니다.
이러한 데이터를 아래와 같은 형식으로 변환하기 위해서는 결국, mysql 클라이언트 (현재 저의 경우 node.js) 에서 데이터 형태를 반복문을 돌며 정리해주는 방법밖에 없을 것 같은데 ... 혹시 이 작업을 효율적으로 할 수 있는 아이디어 있으시면 의견 부탁드립니다.
product : [
{
product_code : 1,
product_name : "의자",
register_date : 1/1,
label : [ { label_code : 1, label_content : "세일상품" }, { label_code : 2, label_content : "인기상품" }, { label_code : 3, label_content : "세트상품" }, { label_code : 4, label_content : "품절임박" } ] }
, {
product_code : 2,
product_name : 책상",
register_date : 1/2,
label : [ { label_code : 1, label_content : "세일상품" }, { label_code : 2, label_content : "인기상품" } ]
}
]
다시 한 번 답변 감사합니다 ㅠ ㅡ ㅠ
SELECT p.code AS product_code, p.name AS product_name, GROUP_CONCAT(l.content separator ', ') AS label FROM product_and_label as pl JOIN product AS p ON pl.product_code=p.code JOIN label as l on pl.label_code=l.code WHERE p.furniture_code=27 (product에 사실 colum이 많습니다.. !) GROUP BY pl.product_code;
계속 고민을 하다 위와 같은 쿼리문을 생각하게 되었는데 아래와 같이 쿼리문을 작성하는 것이 적절한지 (성능적으로나 논리적으로 잘못될 부분이 있을지?) 피드백 가능할까요 ? 주변에 database 관련 질의할 기회가 없어서 대댓글로 질문합니다..ㅠㅠㅠ
감사합니다