2011-10-24 95 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行),每個類別的評分最高。評級計算爲visited/shown

我應該得到36行,其中包含6個頂級類別(我們可以通過AVG(visited/shown)進行排序找到它們)以及這6個類別中的每個類別中的6個頂級網站。

如果您有任何想法如何以不同的方式發生,請告訴我。

+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查詢僅查詢PreQuery,其URL排序順序爲< = 6

爲了進一步確保您只獲得前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