2011-10-24 8 views
3

Mグループのうちの上位N行を選択します。私はこのテーブルを持っている

CREATE TABLE IF NOT EXISTS `catalog_sites` (
    `id` int(10) unsigned NOT NULL auto_increment, 
    `cat_id` int(10) unsigned NOT NULL, 
    `date` datetime NOT NULL, 
    `url` varchar(255) NOT NULL, 
    `title` varchar(255) NOT NULL, 
    `description` varchar(255) NOT NULL, 
    `keywords` varchar(255) NOT NULL, 
    `visited` int(10) unsigned NOT NULL, 
    `shown` int(10) unsigned NOT NULL, 
    `meta_try` int(1) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `url` (`url`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

私は私の問題は簡単であると思いますが、適切な解決策を見つけるように見えるカント..

をので、これはテーブルですウェブサイトでは、6つのカテゴリ(cat_id、合計:36行)で6つのサイトを取得したいと考えています。評価はvisited/shownと計算されます。

6つのトップカテゴリ(私たちはAVG(visited/shown)でソートして見つけることができます)と、これらの6つのカテゴリのそれぞれに6つのトップサイトを含む36行を取得する必要があります。

これがどうやって起こるかについてご意見がありましたら教えてください。

+1

は、ここに私のソリューションです。おそらくこの似たような質問はあなたを助けることができます:http://stackoverflow.com/questions/7602398/selecting-greatest-n-records-in-x-groups/7603343#7603343 –

答えて

1

の制限私はあなたの例を試してみたが、それは本当に私のために動作しない、または私はちょうど私の場合にそれを適応する方法がわかりません。とにかく、私はまだSQLが行く限り、まだnoobですので、私はあなたのクエリを理解することができませんでした。

しかし私は私の問題を解決することができました。それは複雑でおそらく最悪の可能なアプローチです。それも遅いですが、私は結果をキャッシュするので、問題ではありません。それはまったく単純ではない

SET @site_limit = 2; 
SET @cat_limit = 6; 

SET @row = 0; 
SET @limiter = 0; 
SET @last_cat = 0; 

SELECT `cat_id`, `url`, `visited`/`shown` AS `rating`, @limiter := IF(@last_cat = `cat_id`, IF(@limiter >= @site_limit - 1, @limiter, @limiter + 1), 0) AS `limiter`, @last_cat := `cat_id` AS `last_cat` 
FROM `catalog_sites` 
WHERE `cat_id` 
IN (
    SELECT `cat_id` 
    FROM (
     SELECT `cat_id`, @row := @row + 1 AS `row` 
     FROM (
      SELECT `cat_id` 
      FROM `catalog_sites` 
      GROUP BY `cat_id` 
      ORDER BY AVG(`visited`/`shown`) DESC 
     ) AS derived1 
    ) AS derived2 
    WHERE `row` <= @cat_limit 
) 
GROUP BY `cat_id`, `limiter` 
ORDER BY `cat_id`, `rating` DESC 
2

これはMySQL変数を使用して必要なものを取得します。内側のクエリは訪問/表示のランクを事前に計算し、必要な条件による並べ替えを使用します。カテゴリごとに、最も高いランク@varsを使うと@RankSeqが順番に1になるでしょうか?カテゴリごとに。そのPrequery(エイリアスPQ)から、OUTERクエリはURLのランクシーケンスが< = 6

であることをさらに確認するため、内部のPreQueryには事前クエリ/ 「TopCategories」(別名)

select 
     PQ.URL, 
     PQ.Cat_ID, 
     PQ.Rank, 
     PQ.URLRankSeq 
    from 
     (select 
       CS.cat_id, 
       (CS.visited/CS.shown) as Rank, 
       CS.url, 
       @RankSeq := if(@LastCat = CS.Cat_ID, @RankSeq +1, 1) URLRankSeq, 
       @LastCat := CS.Cat_ID as ignoreIt 
      from 
       (select cat_id, 
         avg(visited/shown) 
        from catalog_sites 
        group by 1 
        order by 2 desc 
        limit 6) TopCategories 

       JOIN catalog_sites CS 
       on TopCategories.Cat_ID = CS.Cat_ID, 

       (select @RankSeq := 0, @LastCat = 0) SQLVars 
      order by 
       CS.cat_id, 
       Rank) PQ 
    where 
     PQ.URLRankSeq <= 6 
+0

+1私たちに 'ROW_NUMBER() 'ユーザー定義変数を使用します。 – pilcrow

関連する問題