2014-07-21 47 views
2

下令我有以下字段每種類型的字段:警予 - 選擇前五個記錄日期

Advertisements (
    id bigint 20, 
    name varchar 255, 
    content text, 
    creator_id bigint 20, 
    type_id bigint 255 DEFAULT VALUE IS NULL, 
    create_date bigint 20 
) 

我需要每種類型按日期排序他們選擇前5條記錄(我需要最新遊戲)。我也想用CActiveDataProvider的結果。有沒有什麼方法可以使用模型函數或yii集成函數(sql查詢器除外)獲取記錄(原因:我還需要廣告類中提供的關係)?

UPDATE 其他表:

Users (
    id bigint 20, 
    login varchar 255, 
    password varchar 255, 
    email varchar 255, 
    date_of_registration bigint 20, 
    status varchar 255 
) 
(The table with types) 
Items (
    id bigint 20, 
    item varchar 255, 
    link varchar 255 
) 
Comments (
    id bigint 20, 
    creator_id bigint 20, 
    ...... 
    topic_id bigint 20 
) 
Rating (
    id bigint 20, 
    creator_id bigint 20, 
    ...... 
    topic_id bigint 20 
) 

我想爲每個type_id最新記錄由create_date有序的廣告,如果記錄數超過5一種類型,然後只選擇最新5.還我想要完全登錄創建者+評論數量+評分表格嗎?我知道這可以通過SQL解決,但我沒有任何想法如何去做,因爲我不擅長SQL。任何幫助表示讚賞。感謝所有嘗試提供幫助的人。

+0

可能使用SQL(雖然不是快)。但是甚至會考慮在yii活動記錄或類似的文件中嘗試去做。 – Kickstart

+0

嘗試檢查Yiis的CDbCriteria。 – SnIpY

+0

@SnIpY你能幫我解決這個問題嗎?順便說一句,我知道CDbCriteria。 – iamawebgeek

回答

4

一組詹姆斯K.洛登根據谷歌搜索的提示後,我發現那位未來的答案:

SELECT t.id, 
     t.name, 
     t.content, 
     i.item, 
     c.context 
FROM (SELECT tbl.id, 
      tbl.name, 
      tbl.content, 
      tbl.owner_id, 
      tbl type_id, 
      CASE 
       WHEN tbl.type_id = @category THEN @rownum := @rownum + 1 
       ELSE @rownum := 1 
      END AS num, 
      @category := tbl.type_id 
     FROM Advertisements tbl 
     JOIN (SELECT @rownum := 0, @category := NULL) r 
     ORDER BY tbl.type_id, tbl.create_date DESC) t 
LEFT JOIN Items i ON t.type_id = i.id 
LEFT OUTER JOIN Comments c ON c.topic_id = t.id 
WHERE t.num <= 5 
2

如果我理解你正確的事情應該工作(未測試)。你應該有(TYPE_ID,日期)

// Extract unique types. Perhaps you have table `type` and should do this other way but since you provided info only on Advertisements table I'm using what I got 
$types = YII::app()->db->createCommand("SELECT DISTINCT type_id FROM Advertisements;")->queryColumn(); 

$resultsAll = array(); 
foreach ($types as $type_id) { 
    $results = Advertisments::model()->findAll(
      array("condition" => "type_id = $type_id", "order" => "date DESC", "limit" => 5) 
    ); 
    $resultsAll = array_merge($resultsAll, $results); 
} 

$dataProvider = new CArrayDataProvider($resultsAll, array()); 
+0

我想知道,如果我可以在一個查詢中完成所有這些操作,因爲我的數據庫中有大約8種類型,所以我認爲這不是執行太多查詢的最佳解決方案。但感謝您對我的幫助+1。 – iamawebgeek

+1

這對一個查詢來說非常複雜,我不知道是否可以使用ActiveRecord查詢。本文討論這個問題http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/ – Viacheslav

1

索引我不知道我明白你的意思通過每種類型,或者爲什麼你不希望使用SQL做什麼SQL是爲...設計。

如果使用canonical query排名你的類型,

select a.id, a.name, a.content, 
     a.creator_id, a.type_id, count(b.id) as Rank 
from Advertisements as a join Advertisements as b 
on a.id = b.id 
and a.name = b.name 
and a.content = b.content 
and a.creator_id = b.creator_id 
and a.type_id >= b.type_id 
group by a.id, a.name, a.content, a.creator_id, a.type_id 
having count(b.id) <= 5 

和廣告是通過在GROUP BY子句中的列索引,查詢應在Ø運行(N log n)的時間。在大多數情況下,與O(n)無法區分,這很難被擊敗。

如果您關注性能,可能需要重新考慮列大小。我不知道bigint 20是什麼,但是一個MySQL bigint是64位。你真的希望有超過40億的創作者或類型,你確定這個名字必須超過30個字符嗎?如果您現在製作的選項過於嚴格,所有這些選擇都可以稍後更改,但選擇太多會降低第1天的性能。

+0

我試過你的查詢,它選擇表中的所有記錄。你確定你沒有錯誤嗎?使用SQL沒有任何問題,首先,我正在用所有關係搜索CActiveDataProvider中可用結果的方式,但現在我認爲使用默認模型函數是不可能的。 SQL是好的,如果它選擇與相關的表。 – iamawebgeek

1

使用CDBCriteria。例如:

function actionIndex() 
{ 
    ... 
    $_criteria = new CDbCriteria(); 
    $_criteria->order = 'create_date DESC'; 
    $_criteria->limit = 5; 

    $_ads = new CActiveDataProvider('Advertisements', array('criteria' => $_criteria)); 

    ... 

    $this->render('index', array(
     ... 
     'ads' => $_ads, 
     ... 
    ); 
} 
+0

它將查詢按日期排序的最後5條記錄,但我需要最後(類型數)* 5條記錄,其中每條記錄是表中每種類型中的最新記錄 – iamawebgeek