database.sarang.net
UserID
Passwd
Database
DBMS
ㆍMySQL
PostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
MySQL Q&A 29627 게시물 읽기
No. 29627
쿼리 최적화 질문입니다.//
작성자
최현석(tksanga)
작성일
2010-04-22 14:16
조회수
7,440

안녕하세요..

DB 쿼리를 짜는데 잘 안되네요..T.T

다음과 같은 Order 테이블이 있습니다.

=================================================================

order_id               user_id                       order_date                                                product

1                               A                               2010-04-22   03:11                                   연필

2                               A                               2010-04-22    05:22                                  책

3                               A                               2010-04-23    05:22                                  지우개

4                               B                               2010-04-22     03:22                                  연필

5                               B                               2010-04-23     03:22                                   지우개

==================================================================

이 중에서 각 사용자가 22일 주문한 첫번째 상품을 조회하려고 합니다.

결과

A          연필

B          연필

쿼리를 이렇게 구성했습니다.

select user_id, product

from order

where order_id in ( select min(order_id) from order where order_date>'2010-04-22 00:00:00' and order_date < '2010-04-23 00:00:00' group by user_id )

제 생각에는 서브 쿼리가 메인 쿼리와 연관 관계가 딱히 없는 것 같은데

explain을 하게 되면 Dependent subquery로 나오며, 수행 속도가 상당히 오래 걸립니다.

해결 방안이 없을까요?

이 글에 대한 댓글이 총 4건 있습니다.

 MySQL은 (버전에 따라 다르겠지만) 일반적으로 IN ( .. ) 구문 내 최적화가 잘 안되는 것 같습니다. 일반적으로 생각하기에 IN ( .. ) 구문을 1회 해석후 temporary table에 보관한 후에, non-dependent query로 진행될 것 같은데, 잘 안되더군요. 특별한 경우에는 이를 위해 temporary table을 구성하거나 해서 해결했습니다.

 

그러나 질문해주신 경우는 더 간단하게 해결할 수 있을 것 같습니다.

 

SELECT user_id, product FROM ( SELECT * FROM `order` WHERE order_date >= '2010-04-22 00:00:00' AND order_date < '2010-04-23 00:00:00' ) x GROUP BY user_id;
 
 
더 간단하게, PK인 order_id가 시간 순서와 연관 되어 있고, 테이블이 이에 정렬되어 있다고 가정할 때, 서브쿼리도 필요 없이 아래와 같이 구할 수는 있습니다.
 
SELECT user_id, product FROM `order` WHERE order_date >= '2010-04-22 00:00:00' AND order_date < '2010-04-23 00:00:00' GROUP BY user_id;
 
만약 주기적으로 1번씩만 구하는 것이라면 ALTER TABLE `order` ORDER BY order_id 후에 위의 쿼리를 수행하는 것이 좋지 않을까 생각해봅니다. 애초에 INSERT만 하고 DELETE가 없다면 이도 필요 없겠지요.

 

박현우(lqez)님이 2010-04-22 15:16에 작성한 댓글입니다.

답변 감사드립니다.

제가 원하는 것은 그날 주문한 상품중 첫번째 것을 조회하기를 원하는 것입니다.

박현우님 말씀은 order_id로 이미 시간 순서로 정렬이 되어 있기 때문에

group by를 하게 되면 oder_id가 낮은 것이 자동으로 선택되어 진다는 것인가요?

그럼 첫번째 쿼리의 경우 정렬이 되어있다는 가정이 없으니

SELECT user_id, product FROM ( SELECT * FROM `order` WHERE order_date >= '2010-04-22 00:00:00' AND order_date < '2010-04-23 00:00:00' ) x GROUP BY user_id;

가 아니라

SELECT user_id, product FROM ( SELECT * FROM `order` WHERE order_date >= '2010-04-22 00:00:00' AND order_date < '2010-04-23 00:00:00'  order by order_id asc) x GROUP BY user_id;

되어야 하는 것인가요??

group by 를 이용해서

select a, b

from table

group by a 를 하게 되면 b는 항상 먼저 나오는 a 를 포함한 필드에 값인가요?

 

최현석(tksanga)님이 2010-04-22 15:42에 작성한 댓글입니다.

 댓글에서 제가 잘못 적은 부분이 있군요.

지적해주신대로, ORDER BY order_id ASC 가 빠졌습니다. 작은 샘플을 만들어서 테스트해보다가 실수한 것 같습니다.

 

SELECT a,b FROM table GROUP BY a도 생각하신 것이 맞습니다. 따라서 SELECT MIN(a),b,c FROM table GROUP BY c과 같을 때, b는 MIN(a)와 관계 없는 항상 최초의 값이 됩니다.

박현우(lqez)님이 2010-04-22 18:56에 작성한 댓글입니다.
이 댓글은 2010-04-22 18:57에 마지막으로 수정되었습니다.

친절한 답변 감사드립니당..^^

최현석(tksanga)님이 2010-04-23 09:33에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
29630어떻게 하면 좋을까요. 서브쿼리 문제 [1]
류자현
2010-04-29
7623
29629앞부분의 일부가 일치하는 데이터들을 그룹화해서 얻어오는 법 [2]
제로당
2010-04-26
6884
29628간단한 쿼리 초보입니다. [1]
쿼리왕초보ㅠㅠ
2010-04-23
7582
29627쿼리 최적화 질문입니다.// [4]
최현석
2010-04-22
7440
29626수정된 글 올렸습니다. mysql 기간 검색입니다. 도와주세요. ㅠㅠ [급박] [6]
바램
2010-04-22
9792
29625[질문] mysql 프로시저를 통해 테이블 생성하기. [1]
이근호
2010-04-22
9635
29624[초보] mysql 3.23.58 db생성시 에러 [2]
도날드벅
2010-04-21
7413
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.019초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다