我有一个包含以下字段的表格:
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
一起使用。除了sql查询器之外,有没有办法使用模型函数或yii集成函数获取记录(原因:我还需要在Advertisements类中提供关系)?
更新 其他表:
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
)
如果一个类型的记录数超过5,那么我想在type_id
订购的广告中为每个create_date
提供最新记录,然后只选择最新的5.还要我登录创建者+评论数量+评级表完全?我知道SQL可以解决,但我没有任何想法,因为我不擅长SQL。任何帮助表示赞赏。感谢所有试图提供帮助的人。
答案 0 :(得分: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
答案 1 :(得分:2)
如果我理解你,这样的事情应该有效(未经测试)。你应该有一个索引(type_id,date)
// 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());
答案 2 :(得分: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
和Advertisements由GROUP BY子句中的列索引,查询应在 O(n log n)时间运行。在大多数情况下,这与 O(n)无法区分,这很难被击败。
如果您关注性能,可能需要重新考虑列大小。我不知道bigint 20
是什么,但MySQL bigint是64位。你真的期待超过40亿的创作者或类型,你确定这个名字必须超过30个字符吗?如果您现在制作的选项限制太多,所有这些选择都可以在以后更改,但是太大的选择会在第1天降低性能。
答案 3 :(得分: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,
...
);
}