MySQL을 통해 그룹당 최대 레코드 가져오기
15212 단어 MySQL
제목.
아래 테이블에서 모든 고객(customer id)의 구매금액(amount)의 최대 날짜와 시간(datetime)을 알고 싶습니다.
purchase_id
customer_id
amount
datetime
1
101
100
2000-01-01T00:00:00Z
2
102
180
2000-01-02T00:00:00Z
3
103
200
2000-01-03T00:00:00Z
4
101
70
2000-01-04T00:00:00Z
5
103
280
2000-01-05T00:00:00Z
6
102
310
2000-01-06T00:00:00Z
7
101
10
2000-01-07T00:00:00Z
8
103
280
2000-01-08T00:00:00Z
샘플 데이터
SQL Fiddle 브라우저로 테스트
CREATE TABLE IF NOT EXISTS `purchase_header` (
`purchase_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`customer_id` int(10) unsigned NOT NULL,
`amount` int(10) unsigned NOT NULL,
`datetime` datetime NOT NULL,
PRIMARY KEY (`purchase_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
;
INSERT INTO `purchase_header` (`customer_id`, `amount`, `datetime`) VALUES (101, 100, '2000-01-01 00:00:00');
INSERT INTO `purchase_header` (`customer_id`, `amount`, `datetime`) VALUES (102, 180, '2000-01-02 00:00:00');
INSERT INTO `purchase_header` (`customer_id`, `amount`, `datetime`) VALUES (103, 200, '2000-01-03 00:00:00');
INSERT INTO `purchase_header` (`customer_id`, `amount`, `datetime`) VALUES (101, 70, '2000-01-04 00:00:00');
INSERT INTO `purchase_header` (`customer_id`, `amount`, `datetime`) VALUES (103, 280, '2000-01-05 00:00:00');
INSERT INTO `purchase_header` (`customer_id`, `amount`, `datetime`) VALUES (102, 310, '2000-01-06 00:00:00');
INSERT INTO `purchase_header` (`customer_id`, `amount`, `datetime`) VALUES (101, 10, '2000-01-07 00:00:00');
INSERT INTO `purchase_header` (`customer_id`, `amount`, `datetime`) VALUES (103, 280, '2000-01-08 00:00:00');
안 되는 그림 1 SELECT와 MAX(amount)로 날짜 정렬
이거 내가 MySQL을 처음 기억했을 때 try부터 했어.
SELECT
customer_id, MAX(amount), datetime
FROM
purchase_header
GROUP BY customer_id
;
amount의 최대치를 얻었지만 예상한 데이터를 얻지 못했다.원래 GROUPBY가 지정하지 않았기 때문에 종합되지 않은 데이터에 대해 SELECT를 하는 것은 표준 SQL에서 정확하지 않지만 MySQL에서는 허용된다.
MySQL에서 GRUPBY 처리
모드 1 WHERE 문장의 하위 질의에서 MAX()
하위 조회에서 구매 금액의 최대치를 얻고 외부 조회에서 이와 같은 기록을 표시한다.
SELECT
ph.customer_id, ph.amount, ph.datetime
FROM
purchase_header AS ph
WHERE
ph.amount = (
SELECT
MAX(sub_ph.amount)
FROM
purchase_header AS sub_ph
WHERE
ph.customer_id = sub_ph.customer_id
GROUP BY sub_ph.customer_id
)
;
예기한 결과를 얻었다.최대치가 두 개인 경우에도 두 개를 찾을 수 있다.
단, 관련 하위 조회로서 내부의 하위 조회× 외부 조회에 대한 평가를 통해 원가가 쉽게 높아진다.
EXPLAIN 및 subph는 DEPENDENT SUBQUERY입니다.
모드 2LEFT JOIN을 통한 자가 결합
생각을 바꿔 같은 표를 LEFT JOIN, ON을 활용한다.
pH1보다 큰 기록이 없는 pH2=pH1의 기록이 가장 크다.
ph2는 존재하지 않습니다. IS NULL로 표현됩니다.
SELECT
ph1.customer_id, ph1.amount, ph1.datetime
FROM
purchase_header AS ph1
LEFT JOIN purchase_header AS ph2 ON (ph1.customer_id = ph2.customer_id AND ph1.amount < ph2.amount)
WHERE
ph2.amount IS NULL
;
응, 이 일을 알았을 때 눈을 뜰 수가 없었어.공연도 좋았어요.
모드 3 WHERE NOT EXISTS
@nora1962jp선생님이 주셨어요.감사합니다.
SELECT
ph1.customer_id, ph1.amount, ph1.datetime
FROM
purchase_header AS ph1
WHERE
NOT EXISTS
( SELECT 1 FROM purchase_header AS ph2
WHERE (ph1.customer_id = ph2.customer_id AND ph1.amount < ph2.amount) )
;
모드 4FROM 문에서 GROUPBY, 최대치를 위한 테이블 준비
@shinx55선생님이 주셨어요.감사합니다.
SQL에서 뜻을 쉽게 이해할 수 있고, 속도도 그런대로 괜찮은 다른 방안이다.
SELECT
ph.customer_id AS customer_id, ph.amount AS max_amount, ph.datetime AS datetime
FROM
purchase_header AS ph,
(
SELECT
customer_id, MAX(amount) AS max_amount
FROM
purchase_header
GROUP BY customer_id
) AS mh
WHERE ( ph.customer_id = mh.customer_id AND ph.amount = mh.max_amount )
참고 자료
Reference
이 문제에 관하여(MySQL을 통해 그룹당 최대 레코드 가져오기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/kumagaias/items/c287ced6f2c25a1ba36d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)