我的问题是Doctrine和SQL GroupBy with Order By
所以稍微描述一下有一个商店,商店有文章(a),并且有一个实体访问柜台(vc)来计算不同东西的访问量,也用于商店和文章。
我想要一个文章列表(热门文章),但只是每个商店访问量最大的文章。
class Shop {
private $id;
private $name;
private $is_published;
...
/**
* OneToMany articles
*/
private $articles;
}
class Article {
private $id;
private $name;
private $is_published;
...
/* ManyToOne Shop*/
private $shop;
}
class VisitCounter {
private $id;
private $object_type; //0 for Article, 1 for Shop, 2 for Category
private $object_id;
...
private $nr_alltime_visits;
}
然后我尝试在文章存储库中使用以下查询:
$query = $this->createQueryBuilder('a', 's', 'vc')
->select('a, s')
->leftJoin('a.shop', 's')
->leftJoin('ProjMyBundle:VisitCounter', 'vc', 'WITH', 'vc.object_type = 0 AND cs.object_id= a.id')
->where('a.is_published = 1 AND s.is_published = 1)
->orderBy('vc.nr_alltime_visits', 'DESC')
->groupBy('a.shop');
但是由于我没有得到预期的文章,如果我删除该组,我会得到正确的文章,但每个商店超过1个。
任何想法?
在此问题出现之前,我在Shop和Article(私人$ nr_visits)中有一个字段,然后我有类似的东西(将来可以帮助某人):
$query = $this->createQueryBuilder('a', 's')
->select('a, s')
->where('a.is_published = 1 AND s.is_published = 1')
->leftJoin('a.shop', 's')
->groupBy('a.shop')
->orderBy('nr_visits', 'DESC');
$query->andWhere('a.nr_visits = (SELECT MAX(a2.nr_visits) as nr_visits2 FROM ProjMyBundle:Article AS a2 WHERE a2.is_published = 1 AND a2.shop=a.shop GROUP BY a2.shop)');
答案 0 :(得分:0)
VisitCounter与Shop或Article没有直接关系,因为object_id列依赖于object_type列。那么你就不能使用doctrine的fetch-joins,因为它希望有直接的关系。你必须编写一些原生SQL,但你仍然可以使用一些学说好东西来帮助你制作漂亮的对象(尽管数组更适合读操作)。
至于您的查询,您需要查找“按组排名前N”,这在每个数据库平台上都是不同的(您未在问题中指定)。您必须按文章(和商店)分组,然后对汇总的行执行COUNT(*)。
在这里,您可以阅读如何映射本机sql的结果:http://docs.doctrine-project.org/en/latest/reference/native-sql.html#examples
答案 1 :(得分:0)
可以使用旧版本中的子查询:
$qb->select('a, s, cs')->leftJoin('a.shop', 's')
->leftJoin('ProjMyBundle:VisitCounter', 'vc', 'WITH', 'vc.object_type = :object_type AND cs.object_id=a.id')
->where('a.published = 1 AND s.published = 1)
->andWhere('vc. nr_alltime_visits = (SELECT MAX(vc2.nr_alltime_visits) as hits2 FROM ProjMyBundle:Article AS a2
LEFT JOIN ProjMyBundle:VisitCounter AS vc2 WITH vc2.object_type = :object_type AND vc2.object_id = a2.id
WHERE a2.published = 1 v2.shop=v.shop GROUP BY v2.shop)')
->setParameters(array('object_type' => Clicks::$TYPE_ARTICLE))
->orderBy('cs.nr_alltime_visits', 'DESC')
->groupBy('v.shop')->getQuery()->getResult();