2009-06-04 3 views
4

n 개의 최신 행을받는 방법, 나는 다음과 같은 테이블 구조를 가지고 :MySQL은 : 단순히 내가 할 수있는이 퍼팅 구별 유형

Date | Type | Title

Type의 범위는 1 ~ 10의 값은 , 나는 1,000s의 레코드를 테이블에 가지고 있으며 고유 한 유형의 5 가지 최신 레코드를 원합니다. I 중 하나 만에 DISTINCTType 컬럼에 적용하려는처럼

   Date | Type | Title 
2009-06-04 14:32:00 | 4 | Zeppo 
2009-06-04 14:31:00 | 2 | Groucho 
2009-06-04 14:30:00 | 8 | Harpo 
2009-06-04 14:29:00 | 5 | Gummo 
2009-06-04 14:28:00 | 3 | Chico 

것 같은데, 아니면ORDER BY 절 후 을 적용하는 GROUP BY을 원하는 : 그래서 결과는 같은 것이 될 것이다.

+0

Gummo는 유형이 '2'로되어 있습니까? –

+0

어, 좋은 지적 - 고정! –

답변

2

MySQL의 4의

모든

MySQL 4 위해에서 테스트하지 못했지만, MySQL 5이 쉽게 수행 할 수 있습니다.

테이블이 작동하려면 테이블에 PRIMARY KEY이 있어야합니다. - MySQLGROUP에 대한 N 행을 선택하는 방법

  • Advanced row sampling :
    SELECT l.* 
    FROM (
         SELECT type, 
           COALESCE(
           (
           SELECT id 
           FROM mytable li 
           WHERE li.type= dlo.type 
           ORDER BY 
             li.type DESC, li.date DESC, li.id DESC 
           LIMIT 4, 1 
           ), CAST(0xFFFFFFFF AS DECIMAL)) AS mid 
           COALESCE(
           (
           SELECT date 
           FROM mytable li 
           WHERE li.type= dlo.type 
           ORDER BY 
             li.type DESC, li.date DESC, li.id DESC 
           LIMIT 4, 1 
           ), '9999-31-12') AS mdate 
         FROM (
           SELECT DISTINCT type 
           FROM t_mytable dl 
           ) dlo 
         ) lo, t_mytable l 
    WHERE l.type >= lo.type 
         AND l.type <= lo.type 
         AND (l.date, l.id) >= (lo.mdate, lo.mid) 
    

    가 작동하는 방법에 대한보다 자세한 사항은 내 블로그에서이 항목을 참조하십시오.

이 솔루션을 구현하기 위해 PRIMARY KEY를 추가 할 수없는 경우, 시스템 변수를 사용하여 효율성이 떨어지는 하나를 사용하려고 할 수 있습니다 : 그것은 여기에 설명 된 것

SELECT l.* 
FROM (
     SELECT @lim := 5, 
       @cg := -1 
     ) vars, 
     mytable l 
WHERE CASE WHEN @cg <> type THEN @r := @lim ELSE 1 END > 0 
     AND (@r := @r - 1) >= 0 
     AND (@cg := type) IS NOT NULL 
ORDER BY 
     type DESC, date DESC 

:

업데이트 :

당신이 (결과 집합에서 5 x number of types 기록을 줄 것이다) 각 유형 5 레코드를 선택, 대신 구별 유형과 5 최신 기록 (결과 집합에서 5 기록을 줄 것이다) 선택합니다하지 않으려면

, 이 쿼리를 사용하면 유형이 많이가있는 경우

SELECT date, type, title 
FROM mytable m 
WHERE NOT EXISTS 
     (
     SELECT 1 
     FROM mytable mi 
     WHERE mi.date > m.date 
       AND mi.type = m.type 
     ) 
ORDER BY 
     date DESC 
LIMIT 5 

을,이 GROUP BY을 사용하여, 당신은 date에 대한 인덱스를 제공하는 것이 더욱 효율적입니다.

+0

멋진 기사. 나는 당신이 단지 고급 행 샘플링의 하단에 당신의 속임수 대신에 어떤 인덱스를 사용할지 MySQL에게 알릴 수 있다고 생각한다. http://dev.mysql.com/doc/refman/5.1/en/index-hints.html –

+0

@ Adam : 색인이 사용되지만 두 번째 열에서 USING WHERE와 함께 첫 번째 열에 대한 거친 필터링에만 사용됩니다. 날 믿어, 그 쿼리의 모든 행은 목적에있다 :) – Quassnoi

1

쿼리 성능을 가정하면 다소 중요합니다 그리고 당신은 내가 지금처럼 뭔가 갈 것 MySQL의 4 붙어있어 :

SELECT Date, Type, Title 
FROM (
    SELECT Date, Type, Title 
    FROM Table 
    WHERE Type = 1 
    ORDER BY Date 
    LIMIT 1 

    UNION ALL 

    SELECT Date, Type, Title 
    FROM Table 
    WHERE Type = 2 
    ORDER BY Date 
    LIMIT 1 

    ... 
) x 
ORDER BY Date 
LIMIT 5 

그것은 꽤 아니지만, 그것은 작업을 신속하게 수행하고 취득해야한다. 정기적으로 새 값을 유형 열에 추가하는 경우 쿼리를 정기적으로 수정해야하므로 사용자에게 적합하지 않을 수 있습니다.

파생 테이블이 4 개에 추가 된 것 같습니다.1이므로 4 시리즈에서 적어도 그렇게 높을 필요가 있습니다. 버전 5 또는 다른 데이터베이스를 사용하고 있다면이 문제에 접근 할 수있는 더 좋은 방법이 있습니다.

+0

그것은 4.1, 그래서 파생 테이블을 볼 수도 있습니다. 유감스럽게도이 값은 유지 보수 측면에서 약간의 어려움을 겪을 정도로 자주 변경 될 예정이지만 재미있는 접근 방식입니다. –

1

이것은 union 문과 중첩 된 선택에 대한 좋은 사례 인 것으로 보입니다. 의 라인을 따라

뭔가 :

select t.date, t.type, t.title from (Select top 5 table.Date, table.Type, table.Title from table where type = 1 order by table.date desc) as t 

union 

select t2.date, t2.type, t2.title from (Select top 5 table.Date, table.Type, table.Title from table where type = 2 order by table.date desc) as t2 

[...] 

select t10.date, t10.type, t10.title from (Select top 5 table.Date, table.Type, table.Title from table where type = 10 order by table.date desc) as t10 

order by type, date 

불행하게도, 난 단지 너무 YMMV, 여기에이를 테스트하기 위해 SQL 서버 2008이있다; 하지만 이것은 꽤 기본적인 것들이며 참조 가이드에 따라 mysql 4.0에서 중첩 된 선택과 결합이 모두 지원되므로 작업해야합니다. (mysql 문서를 기반으로 중첩 된 from 문에 as 절을 추가했습니다.)

6

내가 누락 된 항목이 있습니까? 쉬운 해결책은 다음과 같습니다.

SELECT MAX(date) AS max_date, type, title 
FROM table 
GROUP BY 
     type 
ORDER BY 
     max_date DESC 
LIMIT 5 

그리고 매우 빠릅니다.

+0

@ Adam : 나는 당신의 솔루션이 정말로 그것이 무엇인지 저자가 생각하는 것 같지만, _says_와 같이 "각 유형의 5 개의 가장 최근 기록"을 반환하지 않습니다. – Quassnoi

+0

@ Adam :하지만 어쨌든 +1이라고 생각합니다. – Quassnoi

0

내가 단지 MySQL의 5에 그것을 시도했습니다이

select 
    T.* 
from 
     (select 
      max(date) dt, 
      Type 
     from 
      table 
     group by type 
     order by dt desc 
     limit 5) subQuery 
     inner join table T on T.date = subQuery.dt and T.Type = subQuery.Type 

이 날짜 필드가 고유 한 가정 한 것입니다보십시오. 날짜가 아닌 기본 키가있는 경우 해당 키를 쿼리에 사용하십시오.

0

나는 조금 늦었다 고 알고있다. 그러나 같은 문제가 있었고 어떻게 알아 냈다. 나는 게시하고있다.

SELECT t.Date, t.Type, t.Title 
FROM (SELECT Date, Type, Title FROM table ORDER BY Date DESC) AS t 
GROUP BY t.Type LIMIT 5; 

나는 더 간단한 해결책이 있다고 생각하지 않습니다.

설명은

  1. 내부 SELECT 먼저 실행 얻는다. 행이 있고 DESC가 날짜 열에 정렬 된 표가 반환됩니다. 이 표에서는 의 최신 항목이 특정 유형의 다른 모든 항목보다 우선합니다. 이 반환 테이블의 이름이 t로 바뀝니다.

  2. 이제 유형 열을 기반으로이 테이블에서 GROUP BY 연산이 수행됩니다. 결과는 각 유형의 첫 번째 행입니다.

  3. 이제 LIMIT 조건을 에 추가하면 처음 5 개의 행을 가져옵니다.