我有一个包含以下字段的表:
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集成函数获得记录(原因:我还需要在广告类中提供关系)?
其他表:
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
)
我想拥有create_date
订购的广告中每个type_id
的最新记录,如果一个类型的记录数量超过5,则只选择最近的5条。另外,我想有登录的创建者+评论数+评级表完全?我知道这是可以通过SQL解决的,但我不知道如何做到这一点,因为我不擅长SQL。任何帮助都是感激的。谢谢大家的帮助。
根据James K. Lowden的提示在谷歌上搜索了一组后,我找到了下一个答案:
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
如果我理解你的权利,这样的东西应该工作(未测试)。你应该在(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());
我不确定我理解你所说的每个类型 是什么意思,或者为什么你不想用SQL来做SQL设计的目的。
如果使用规范查询对类型进行排序,
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
and advertising由GROUP by子句中的列索引,查询运行时间为O(n log n)。在大多数情况下,它与O(n)难以区分,这很难被打败。
如果您关心性能,您可能需要重新考虑列的大小。我不知道bigint 20
是什么,但是MySQL的bigint是64位。你真的期望超过40亿个创作者或类型吗?你确定名字必须超过30个字符吗?如果您现在做出的选择限制太大,那么以后可以更改所有这些选择,但是太大的选择将从第一天开始降低性能。
使用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,
...
);
}