2009-07-07 11 views
2

私のデータでは、カテゴリごとに最新の2つのアイテムを取得するために、どのように次のようになりますは、1つの選択(MySQLで)

 
id|category|insertdate|title.... 
-------------------------------- 
1|1|123|test 1 
2|1|124|test 2 
3|1|125|test 3 
4|2|102|test 4 
5|2|103|test 5 
6|2|104|test 6 

私はカテゴリごとに(順番に最新の2つのエントリを取得されて達成しようとしますinsertdate DESCによる)、結果がでなければなりませんので:group byを使用して、最新の入手

 
id|.... 
---- 
3|.... 
2|.... 
6|.... 
5|.... 

は簡単ですが、どのように私は、複数のクエリを起動せずに、最新の2を得るのですか?任意の助け

おかげで;-)
S.

答えて

3

ここであなたはバディーになります!

SET @counter = 0; 
SET @category = ''; 

SELECT 
    * 
FROM 
(
    SELECT 
     @counter := IF(data.category = @category, @counter+1, 0) AS counter, 
     @category := data.category, 
     data.* 
    FROM 
    (
     SELECT 
      * 
     FROM test 
     ORDER BY category, date DESC 
    ) data 
) data 
HAVING counter < 2 
+0

。 – Welbog

+0

私はHAVINGを2番目の副選択に入れようとしましたが、カウンタは "まだこの時点で設定されていませんでした"または "オプティマイザが@counterの前に実行していました" ...したがって、もちろんWHEREは外部1。 –

0

あなたは1つのSELECT文でクエリのこの種を行うできるようにするつもりはないが、あなたが返す1つのストアドプロシージャでそれをラップすることができますサブクエリの結果を各カテゴリの一時テーブルに追加してから1つのデータセットを作成した後、一時テーブルの内容を返します。

擬似コード:

Create a temp table 
For each distinct category, 
    Add the last two records to the temp table 
Return the temp table 

あなたが最後にしたいデータのセットになってしまいますし、アプリケーションの観点から一つだけのクエリが行われました。

0

別の方法は、group_concatを使用して順序付きリストを取得することです。あなたが多くのデータを持っていたとしても、これは本当に役に立たないでしょう。

select group_concat(id order by insertdate desc separator ','), category from tablename group by category 

またはサブ選択(このmysqlの上に)

select category, 
    (select id from test as test1 where test1.category = test.category order by insertdate desc limit 0,1) as recent1, 
    (select id from test as test1 where test1.category = test.category order by insertdate desc limit 1,1) as recent2 
from test 
group by category; 

を使用して私は2番目のオプションは、それは私がやって見ることができる唯一の方法だが、サブクエリがあるとして選択し、技術的ものではありません知っていますそれ。

7

これが最善の問題をカバーする優れた、詳細な記事にあなたを向けることによって回答されたSQLでのトリッキーな問題がある:How to select the first/least/max row per group in SQL。これには、MySQL固有の手段と一般的な方法が含まれています。 WHEREカウンタ<2の代わりにHAVINGのが、潜在的に非効率的な場合、それはすべてのレコードを経る必要があるため、それは、理想的な答えだということ以外にする必要があります

+3

優れたリソース!その中のより詳細な詳細を網羅したはるかに網羅的な答え。 –

0
SELECT * 
FROM category AS c1 
WHERE (
    SELECT COUNT(c2.id) 
    FROM category AS c2 
    WHERE c2.id = c1.id AND c2.insertdate > c1.insertdate 
) < 2 
関連する問題