2009-06-04 2 views
4

のnは最新の行を取得する方法、私は次の表の構造を持っている:MySQLは:単に私ができるようにこれを置く特殊タイプ

Date | Type | Title

セイTypeは1〜10の範囲内の値であります私はテーブルに1000sのレコードを持っています。私はユニークなタイプの5つの最新のレコードが必要です。だから、結果は次のようなものになるだろう:

   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 

私はどちらかだけType列に適用するか、私はORDER BY句の後を適用しますGROUP BYをしたいのDISTINCTをしたいように思えます。

のMySQL 4のすべての

+0

Gummoのタイプは「2」ですか? –

+0

まあ、良い点 - 修正! –

答えて

2

MySQL 4ためでテストしていないが、MySQL 5では、これは簡単に行うことができます。

これを行うには、テーブルにPRIMARY KEYのようなものが必要です。

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を追加することができない場合は、システム変数を使用して効率の低い1使ってみてください可能性があります。それは、ここで説明しています

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レコードを与えることになる)(結果セットに5 x number of typesレコードを与えるだろう)各タイプの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:索引が使用されますが、最初の列の粗いフィルタリングと2番目の列の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 

は、私はここでこれをテストするために、SQL Server 2008を持っているので、メーリングリストへ。これはかなり基本的なものであり、参照ガイドに従ってmysql 4.0でネストされた選択と共用体の両方がサポートされているので、動作するはずです。 (私はmysqlのドキュメントに基づいて入れ子のステートメントにas句を追加しました)

6

私に何か不足していますか?簡単な解決策は、次のようになります。

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

これは非常に速いはずです。

+0

@アダム:私はあなたの解決策が実際に何を意味するのかを考えていますが、_says_のように「各タイプの5つの最新のレコード」を返しません。 – Quassnoi

+0

@Adam:でも、とにかく+1だと思います。 – Quassnoi

0

この

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 

を試してみてください私はこれは、日付フィールドが一意であると仮定しているのMySQL 5上でそれを試してみました。 date以外の主キーがある場合は、そのキーをクエリで使用します。

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; 

私は単純な解決策はないと思います。

内側SELECTが最初に実行されます説明

  1. 。これにより、 行の表が戻され、日付列にソートされたDESCが戻されます。この表では、特定のタイプの の最新のエントリは、特に同じタイプの他のエントリです。 この戻り表の名前がtに変更されました。

  2. これで、Typeテーブルに基づいてこのテーブルに対してGROUP BY操作が実行されました。 結果は各タイプの最初の行です。

  3. にLIMIT条件を追加します。最初の5行を取得します。

関連する問題