Bestill ved innen gruppen av i Lære 2

stemmer
5

Jeg bruker Symfony 2 PR12 med Lære to og MySQL. Jeg har en database lagring artikler og utsikt over disse artiklene:

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

    // ...
}

Jeg ønsker å få, for eksempel de 20 mest nylig sett artikler. Min første tanke ville være noe sånt som:

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

Imidlertid, når det er mer enn ett vis tilordnet en gjenstand, vil rekkefølgen-by / gruppe-av kombinasjonen gir uventede resultater for rekkefølgen.

Dette er forventet oppførsel for MySQL, siden gruppering håndteres før bestilling, og det er arbeids rå-spørring løsninger på dette problemet ved http://www.artfulsoftware.com/infotree/mysqlquerytree.php (Aggregater -> Innen-gruppen aggregater) . Men jeg kan ikke finne ut hvordan å oversette noen av disse løsningene i DQL, siden så vidt jeg kan fortelle det er ingen måte å velge fra subqueries eller utføre selvekskluderings tiltrer.

Noen ideer om hvordan man kan løse problemet med rimelig ytelse?

Publisert på 23/04/2011 klokken 21:02
kilden bruker
På andre språk...                            


1 svar

stemmer
8

Jeg endte opp med å løse det med en korrelert delspørring:

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

På den måten slags ignorerer ArticleView er annet enn den siste for en gitt artikkel. Selv om min gjetning er at dette fungerer ganske dårlig i forhold til de andre rå SQL løsninger - noen svar med bedre ytelse vil fortsatt bli verdsatt :).

Svarte 29/04/2011 kl. 18:48
kilden bruker

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