내 테이블은 :
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
3 | 10 | 03/03/2009 | john | 300
4 | 11 | 03/03/2009 | juliet | 200
6 | 12 | 03/03/2009 | borat | 500
7 | 13 | 24/12/2008 | borat | 600
8 | 13 | 01/01/2009 | borat | 700
home
최대 값을 보유한 각 고유 항목을 선택해야합니다 datetime
.
결과는 다음과 같습니다.
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
8 | 13 | 01/01/2009 | borat | 700
나는 시도했다 :
-- 1 ..by the MySQL manual:
SELECT DISTINCT
home,
id,
datetime AS dt,
player,
resource
FROM topten t1
WHERE datetime = (SELECT
MAX(t2.datetime)
FROM topten t2
GROUP BY home)
GROUP BY datetime
ORDER BY datetime DESC
작동하지 않습니다. 데이터베이스에 187 개가 있지만 결과 집합에 130 개의 행이 있습니다. 결과에의 일부 중복이 포함됩니다 home
.
-- 2 ..join
SELECT
s1.id,
s1.home,
s1.datetime,
s1.player,
s1.resource
FROM topten s1
JOIN (SELECT
id,
MAX(datetime) AS dt
FROM topten
GROUP BY id) AS s2
ON s1.id = s2.id
ORDER BY datetime
아니. 모든 기록을 제공합니다.
-- 3 ..something exotic:
다양한 결과로.
답변
당신은 너무 가깝습니다! 집과 최대 날짜 시간 topten
을 모두 선택한 다음 BOTH 필드 의 테이블에 다시 가입하기 만하면됩니다.
SELECT tt.*
FROM topten tt
INNER JOIN
(SELECT home, MAX(datetime) AS MaxDateTime
FROM topten
GROUP BY home) groupedtt
ON tt.home = groupedtt.home
AND tt.datetime = groupedtt.MaxDateTime
답변
MySQL
내부 쿼리가없고없는 가장 빠른 솔루션 GROUP BY
:
SELECT m.* -- get the row that contains the max value
FROM topten m -- "m" from "max"
LEFT JOIN topten b -- "b" from "bigger"
ON m.home = b.home -- match "max" row with "bigger" row by `home`
AND m.datetime < b.datetime -- want "bigger" than "max"
WHERE b.datetime IS NULL -- keep only if there is no bigger than max
설명 :
home
열을 사용하여 테이블 자체를 조인하십시오 . 를 사용 LEFT JOIN
하면 테이블의 모든 행 m
이 결과 집합에 나타납니다. 테이블에서 일치하지 않는 항목은 의 열에 대해을 b
갖습니다 .NULL
b
의 다른 조건은의 JOIN
행 보다 열의 b
값이 큰 행만 일치하도록 요청합니다 .datetime
m
질문에 게시 된 데이터를 사용하면 다음과 LEFT JOIN
같은 쌍이 생성됩니다.
+------------------------------------------+--------------------------------+
| the row from `m` | the matching row from `b` |
|------------------------------------------|--------------------------------|
| id home datetime player resource | id home datetime ... |
|----|-----|------------|--------|---------|------|------|------------|-----|
| 1 | 10 | 04/03/2009 | john | 399 | NULL | NULL | NULL | ... | *
| 2 | 11 | 04/03/2009 | juliet | 244 | NULL | NULL | NULL | ... | *
| 5 | 12 | 04/03/2009 | borat | 555 | NULL | NULL | NULL | ... | *
| 3 | 10 | 03/03/2009 | john | 300 | 1 | 10 | 04/03/2009 | ... |
| 4 | 11 | 03/03/2009 | juliet | 200 | 2 | 11 | 04/03/2009 | ... |
| 6 | 12 | 03/03/2009 | borat | 500 | 5 | 12 | 04/03/2009 | ... |
| 7 | 13 | 24/12/2008 | borat | 600 | 8 | 13 | 01/01/2009 | ... |
| 8 | 13 | 01/01/2009 | borat | 700 | NULL | NULL | NULL | ... | *
+------------------------------------------+--------------------------------+
마지막 WHERE
으로이 절 NULL
은 열에 s 가있는 쌍만 유지합니다 b
( *
위의 표에 표시되어 있음 ). 이는 JOIN
절의 두 번째 조건으로 인해에서 선택된 행 m
이 column에서 가장 큰 값을 갖음을 의미 datetime
합니다.
다른 SQL 팁에 대해서는 SQL 안티 패턴 : 데이터베이스 프로그래밍의 함정 피하기 책을 읽으십시오 .
답변
다음은 T-SQL 버전입니다.
-- Test data
DECLARE @TestTable TABLE (id INT, home INT, date DATETIME,
player VARCHAR(20), resource INT)
INSERT INTO @TestTable
SELECT 1, 10, '2009-03-04', 'john', 399 UNION
SELECT 2, 11, '2009-03-04', 'juliet', 244 UNION
SELECT 5, 12, '2009-03-04', 'borat', 555 UNION
SELECT 3, 10, '2009-03-03', 'john', 300 UNION
SELECT 4, 11, '2009-03-03', 'juliet', 200 UNION
SELECT 6, 12, '2009-03-03', 'borat', 500 UNION
SELECT 7, 13, '2008-12-24', 'borat', 600 UNION
SELECT 8, 13, '2009-01-01', 'borat', 700
-- Answer
SELECT id, home, date, player, resource
FROM (SELECT id, home, date, player, resource,
RANK() OVER (PARTITION BY home ORDER BY date DESC) N
FROM @TestTable
)M WHERE N = 1
-- and if you really want only home with max date
SELECT T.id, T.home, T.date, T.player, T.resource
FROM @TestTable T
INNER JOIN
( SELECT TI.id, TI.home, TI.date,
RANK() OVER (PARTITION BY TI.home ORDER BY TI.date) N
FROM @TestTable TI
WHERE TI.date IN (SELECT MAX(TM.date) FROM @TestTable TM)
)TJ ON TJ.N = 1 AND T.id = TJ.id
편집
불행히도 MySQL에는 RANK () OVER 함수가 없습니다.
그러나 에뮬레이션 할 수 있습니다 (MySQL로 분석 (AKA 순위) 함수 에뮬레이션 참조 ) .
따라서 이것은 MySQL 버전입니다.
SELECT id, home, date, player, resource
FROM TestTable AS t1
WHERE
(SELECT COUNT(*)
FROM TestTable AS t2
WHERE t2.home = t1.home AND t2.date > t1.date
) = 0
답변
이것은 당신이 각각 두 개 이상의 행이있을 경우에도 작동합니다 home
동일한와 DATETIME
의 :
SELECT id, home, datetime, player, resource
FROM (
SELECT (
SELECT id
FROM topten ti
WHERE ti.home = t1.home
ORDER BY
ti.datetime DESC
LIMIT 1
) lid
FROM (
SELECT DISTINCT home
FROM topten
) t1
) ro, topten t2
WHERE t2.id = ro.lid
답변
나는 이것이 당신에게 원하는 결과를 줄 것이라고 생각합니다 :
SELECT home, MAX(datetime)
FROM my_table
GROUP BY home
그러나 다른 열도 필요하면 원래 테이블과 조인하십시오 ( Michael La Voie
답변 확인 ).
친애하는.
답변
사람들 이이 스레드를 계속 실행하는 것처럼 보이기 때문에 (댓글 날짜 범위는 1.5 년입니다) 그리 간단하지 않습니다.
SELECT * FROM (SELECT * FROM topten ORDER BY datetime DESC) tmp GROUP BY home
집계 함수가 필요하지 않습니다 …
건배.
답변
이것을 시도해 볼 수 있으며 큰 테이블의 경우 쿼리 성능이 향상됩니다. 각 가정에 대해 두 개 이상의 레코드가없고 날짜가 다른 경우 작동합니다. 더 나은 일반적인 MySQL 쿼리는 위의 Michael La Voie의 쿼리입니다.
SELECT t1.id, t1.home, t1.date, t1.player, t1.resource
FROM t_scores_1 t1
INNER JOIN t_scores_1 t2
ON t1.home = t2.home
WHERE t1.date > t2.date
또는 Postgres 또는 분석 기능을 제공하는 DB의 경우
SELECT t.* FROM
(SELECT t1.id, t1.home, t1.date, t1.player, t1.resource
, row_number() over (partition by t1.home order by t1.date desc) rw
FROM topten t1
INNER JOIN topten t2
ON t1.home = t2.home
WHERE t1.date > t2.date
) t
WHERE t.rw = 1