2012-10-05 4 views
6

비슷한 유형의 질문을 보았지만 아무도 내 상황을 도왔습니다.ID와 최신 날짜순으로 MySQL 그룹

나는 테이블이

테스트는 다음 스키마가 테스트 (사용하여 MySQL의의 MyISAM)을 말할 수있다 : 지금 테스트 페이지는 현재 로그인 한 사용자가 방문 할 때마다

TID INT PRIMARY KEY AUTO_INCREMENT 
    TData varchar (data that i want to select) 
    TUserID INT (this will be joined with users table, same users can have many records here) 
    TViewedAt DATETIME (records each time user visits page, datetime format) 

를,이 기록을 추가 이 테이블에는 방문한 사용자 ID, 사용자가 방문한 일부 데이터 및 날짜 및 시간이 매번 자동으로 증가되는 TID로 기록됩니다.

그런 다음 백엔드 관리 페이지에서 어떤 사용자가 테스트 페이지를 방문했는지, 얼마나 많은 시간, 데이터 및 시간을 볼 수 있는지 확인하십시오. 기본적으로 20-25 개의 최신 행 목록이있는 테이블입니다. 내 쿼리는 데이터 당 하나의 레코드 만 선택해야합니다. 데이터는 사용자가 동일 할 수 있지만 다른 시간에 있지만 가장 최근의 각 사용자에 대해 하나의 데이터 만 선택하려고합니다. 따라서 사용자가 테스트 페이지를 10 번 방문하면 10 개의 레코드가 데이터베이스로 이동하지만 테이블에는 최신 레코드가 1 개만 표시됩니다. 다른 사용자가 15 번 페이지를 방문하면이 두 번째 사용자에 대한 1 개의 레코드가 표시됩니다.이 두 번째 사용자는 가장 최근의 레코드이므로 총 2 개의 행이 테이블에 표시됩니다. 어떤 이유로 든 GROUP BY를 사용할 수 있지만 MAX (날짜)는 각 날짜의 최신 datetime을 제공하지 않습니다. 이는 중

SELECT * 
    FROM Test 
    WHERE TUserID = 123 
    GROUP BY TData 
    ORDER BY TViewedAt 

수익률이 행을 해당 행의 어느 것도 최신 없습니다 :

여기 내 쿼리입니다.

덕분에 많이

답변

11

다음과 같이하면 필요한 것을 얻을 수 있다고 생각합니다. 이러한 작업을 "그룹 별 최대"라고합니다. 옵션 1

이 이해하기 쉬운이며, 하위 쿼리가 max 이후 모든 사용자에 대해 최대 TID를 반환합니다

Group By와 함께 사용되며 우리가 다른 쿼리를보다 모든 데이터를 얻을 수 그 신분증들.

Select TID, TData, TUserID, TViewedAt 
From Test 
Where TID In(
    Select Max(TID) 
    From Test 
    Group By TUserID 
) 

옵션 2

약간 더 복잡한 이해하기하지만, 가장 가능성이 더 효율적이 t1.TViewedAt가 최대 값에있을 때, 더 큰 값을 더 t2.TViewedAt가 없음을 기준으로 작동 t2 행의 값은 NULL이됩니다. 쿼리에 따라

SELECT t1.TID, t1.TData, t1.TUserID, t1.TViewedAt 
FROM Test t1 
LEFT JOIN Test t2 ON t1.TUserID = t2.TUserID AND t1.TViewedAt < t2.TViewedAt 
WHERE t2.TUserID IS NULL; 

결과

TID TData TUserID TViewedAt 
4 test3 123  2012-10-05 00:00:00.000 
5 test2 213  2012-10-03 00:00:00.000 
+0

네, 그 일이 매우 대단히 간단하고 쉽게 대단히 감사합니다 – Giorgi

+0

환영합니다, 기꺼이 도와 드리겠습니다 –

+1

거기에 어떤 방법이 있습니다 그게 더 효율적입니다, 즉, 하위 쿼리가 필요하지 않습니다? 내 서버를 죽이고 있다는 것을 발견했습니다 – Jason

1

당신은 최대 집계에 대한 GROUP BY TUserID해야합니다.

SELECT 
    TID, 
    TData, 
    main.TUserID 
    main.TViewedAt 
FROM 
    yourTable main 
    JOIN ( 
    SELECT TUserID, MAX(TViewedAt) AS TViewedAT FROM yourTable GROUP BY TUserID 
) tmax ON main.TUserID = tmax.TUserID AND main.TViewedAt = tmax.TViewedAt 

이것은 하위 쿼리와 조인하는 이식 가능한 방법입니다. 하위 쿼리는 사용자 당 최신 TUserID,TViewedAt을 가져오고 기본 테이블과 다시 결합되어 일치하는 TData을 가져옵니다.

당신은 한 번에 하나의 사용자를 원하는 경우에, 당신이 할 수 있습니다

SELECT 
    TData, 
    TViewedAt 
FROM yourTable 
WHERE TUserID = 'someid' 
GROUP BY TUserId 
HAVING TViewedAt = MAX(TViewedAt) 

위의 내용에만 MySQL의에서 그래도 난 그것을 쓴 방식으로 작동합니다. 다른 RDBMS는 TDataSELECT 목록에 있지만 GROUP BY에는없는 사실에 대해 불만을 토로합니다.

+0

두 번째 도움 0 행을 반환 할 수 있습니다. TViewedAt는 DATETIME 형식입니까? – Giorgi

+1

@Giorgi MAX()는 datetime 열을 인식합니다. 첫 번째 문장을 사용하지만 WHERE 절을 추가하여 원하는 사용자를 제한하십시오. 첫 번째는 두 가지가 더 좋고 휴대하기 쉽습니다. –

0
SELECT t1.TData, t1.TUserID, t1.TViewedAt 
FROM Test t1 
JOIN 
(SELECT TUserID, MAX(TViewedAt) 
FROM Test 
GROUP BY TUserID) t2 
ON t1.TUserID = t2.TUserID AND t1.TViewedAt=t2.TViewedAt 
+0

그 didnt 일 :( – Giorgi

+0

죄송합니다, 그 TData 다를 수 있습니다 놓친 다음 ... 업데이 트를 참조하십시오 ... – alex

1

, 내가 시도 당신이 -

select * from pages where date(create_date)=(select date(create_date) from pages order by create_date limit 1) 
+1

질문에 대한 답변을 설명해 주시겠습니까? – Braiam