MySQL 쿼리문 질문드립니다 0 5 161

by 변은빈 [2020.06.29 16:11:22]


안녕하세요. 저는 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. 로직은 맞지만 데이터 베이스 설정값 ??등에 문제가 있어서 성능이 안나오는건지 

고수님들의 의견 기다리겠습니다.

 

읽어주셔서 감사합니다.

 

 

by 마농 [2020.06.29 16:51:17]

두번째 쿼리에서 처럼 조인쿼리를 사용하시면 됩니다.
단, 특정 상품코드 조건을 빼고, 전체 조회로 하시면 됩니다.

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
;

 


by 변은빈 [2020.06.29 17:24:47]

 

미농님 친절한 답변 감사합니다. 미농님께서 작성해주신 쿼리문을 실행하게 된다면 아래와 같은 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 : "인기상품" } ]

}

]

 

다시 한 번 답변 감사합니다 ㅠ ㅡ ㅠ 


by 변은빈 [2020.06.29 18:01:54]
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 관련 질의할 기회가 없어서 대댓글로 질문합니다..ㅠㅠㅠ 

 

감사합니다


by 마농 [2020.06.30 10:21:34]

작성하신 쿼리가 원하는 결과를 도출할 수 있다면 그렇게 사용하시면 됩니다.
다만, 그룹바이 표준에 어긋나는 문법입니다.
MySQL 에서는 에러 없이 돌아가긴 하겠지만, 표준에 맞게 고치는게 좋겠네요.
- 변경전 : GROUP BY pl.product_code
- 변경후 : GROUP BY p.code, p.name
 


by 변은빈 [2020.06.30 11:08:26]

며칠동안 답답했는데 많이 배웠습니다.

마농님 답변 감사합니다 .. ! 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입