6

Doctrine 2 と MySQL で Symfony 2 PR12 を使用しています。記事とそれらの記事のビューを格納するデータベースがあります。

// ...
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;

    // ...
}

たとえば、最近閲覧した 20 件の記事を取得したいと考えています。私の最初の考えは次のようなものです:

$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)
;

ただし、記事に複数のビューが関連付けられている場合、order-by/group-by の組み合わせにより、順序付けに予測できない結果が生じます。

グループ化は注文前に処理され、 http ://www.artfulsoftware.com/infotree/mysqlquerytree.php (集約 -> グループ内集約)でこの問題に対する有効な未処理のクエリ ソリューションがあるため、これは MySQL の予想される動作です。 . しかし、これらのソリューションを DQL に変換する方法がわかりません。なぜなら、サブクエリから選択したり、自己除外結合を実行したりする方法がないからです。

合理的なパフォーマンスで問題を解決する方法についてのアイデアはありますか?

4

1 に答える 1

8

私は相関サブクエリでそれを解決することになりました:

$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)')

こうすることで、並べ替えは特定の記事の最新以外の ArticleView を無視します。私の推測では、これは他の生の SQL ソリューションに比べてパフォーマンスがかなり悪いと思いますが、パフォーマンスが向上した回答は大歓迎です :)。

于 2011-04-29T18:48:44.643 に答える