ORDER BY dentro do grupo por em Doutrina 2

votos
5

Estou usando Symfony 2 PR12 com Doutrina 2 e MySQL. Eu tenho um banco de dados de armazenamento de artigos e pontos de vista desses artigos:

// ...
class Article {

    /**
     * @orm:Column(type=bigint)
     * @orm:Id
     * @orm:GeneratedValue
     * @var int
     */
    protected $id;

    /**
     * @orm:OneToMany(targetEntity=ArticleView,mappedBy=article)
     * @var ArrayCollection
     */
    protected $views;

    // ...
}

// ...
class ArticleView {

    /**
     * @orm:Column(type=bigint)
     * @orm:Id
     * @orm:GeneratedValue
     * @var int
     */
    protected $id;

    /**
     * @orm:Column(type=bigint,name=DateRead,nullable=true)
     * @var int
     */
    protected $viewDate;

    /**
     * @orm:ManyToOne(targetEntity=Article,inversedBy=views)
     * @var Article
     */
    protected $article;

    // ...
}

Eu quero ficar, por exemplo, os 20 artigos mais recentemente visualizados. Meu primeiro pensamento seria algo como:

$qb = <instance of Doctrine\ORM\QueryBuilder>;
$qb->select('a')
   ->from('Article', 'a')
   ->join('a.views', 'v')
   ->orderBy('v.viewDate', 'DESC')
   ->groupBy('a.id')
   ->setMaxResults(20)
;

No entanto, quando há mais do que um ponto de vista relacionado com um artigo, o fim-de / grupo-por combinação dá resultados imprevisíveis para a ordenação.

Este é o comportamento esperado para o MySQL, uma vez que o agrupamento é tratado antes de pedir, e há soluções de consulta matéria de trabalho para este problema na http://www.artfulsoftware.com/infotree/mysqlquerytree.php (Agregados -> agregados dentro do grupo) . Mas eu não consigo descobrir como traduzir qualquer uma destas soluções em DQL, já que, tanto quanto eu posso dizer não há nenhuma maneira de selecionar a partir de subconsultas ou realizar auto-exclusão junta.

Todas as ideias sobre como resolver o problema com um desempenho razoável?

Publicado 23/04/2011 em 22:02
fonte usuário
Em outras línguas...                            


1 respostas

votos
8

Acabei resolvê-lo com uma subconsulta correlacionada:

$qb
    ->select('a')
    ->from('Article', 'a')
    ->join('a.views', 'v')
    ->orderBy('v.viewDate', 'DESC')
    ->setMaxResults(20)

    // Only select the most recent article view for each individual article
    ->where('v.viewDate = (SELECT MAX(v2.viewDate) FROM ArticleView v2 WHERE v2.article = a)')

Dessa forma, o tipo ignora ArticleView do outro do que a mais recente de um determinado artigo. Embora o meu palpite é que este executa bastante mal em relação às outras soluções SQL cru - quaisquer respostas com melhor desempenho ainda seria muito apreciada :).

Respondeu 29/04/2011 em 19:48
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more