2012-04-16 76 views
7

我使用Symfony的2學說,和我有兩個實體加入了一個多對多關聯。 比方說,我有兩個實體:用戶和組,並在數據庫的相關表是用戶,組和users_groups。DQL多對多和計數

我想在DQL中獲得排名前10位的人數最多的羣組,但我不知道在連接表(users_groups)上執行查詢的語法。我已經看過的教義手冊,但我沒有找到解決辦法,我想我還是有很多瞭解DQL。

在普通的SQL,這將是:

select distinct group_id, count(*) as cnt from users_groups group by group_id order by cnt desc limit 10 

能否請你幫我翻譯這DQL?

更新(類):

/** 
* Entity\E_User 
* 
* @ORM\Table(name="users") 
* @ORM\Entity 
*/ 
class E_User 
{ 
    /** 
    * @ORM\ManyToMany(targetEntity="E_Group", cascade={"persist"}) 
    * @ORM\JoinTable(name="users_groups", 
    *  joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="cascade")}, 
    *  inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id", onDelete="cascade")} 
    *) 
    */ 

    protected $groups; 

    /** 
    * @var integer $id 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string $name 
    * 
    * @ORM\Column(name="name", type="string", length=255) 
    */ 
    private $name; 

    /* ... other attributes & getters and setters ...*/ 
} 


/** 
* Entity\E_Group 
* 
* @ORM\Table(name="groups") 
* @ORM\Entity 
*/ 
class E_Group 
{ 
    /** 
    * @var integer $id 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string $name 
    * 
    * @ORM\Column(name="text", type="string", length=255) 
    */ 
    private $name; 

    /* ... other attributes & getters and setters ...*/ 
} 

回答

6

這並不容易,沒有看到實際的課程,而是通過猜測你有很多一對多的雙向關係:

$dql = "SELECT g.id, count(u.id) as cnt FROM Entity\Group g " . 
    "JOIN g.users u GROUP BY g.id ORDER BY cnt DESC LIMIT 10;"; 
$query = $em->createQuery($dql); 
$popularGroups = $query->getArrayResult(); 

更新:

你不使用雙向關係,你可以曲ERY周圍的其他方法:

$dql = "SELECT g.id, count(u.id) as cnt FROM Entity\User u " . 
    "JOIN u.groups g GROUP BY g.id ORDER BY cnt DESC LIMIT 10;"; 
+0

謝謝,問題在於Group實體沒有一個叫做用戶的關聯。所以,我得到異常:語義錯誤] 0行,列72附近的GROUP BY g.id「:錯誤:類實體\ E_Group沒有協會命名的用戶。我用實際的課程更新了這個問題。我們要加一個$用戶屬性來E_Group實體進行雙向許多一對多的關係? – 2012-04-19 10:05:32

+0

非常感謝。無論如何,我結束了雙向關係。這只是一個虛擬查詢,以瞭解它是如何工作的。再次感謝 – 2012-04-21 10:34:18

0

對於那些誰想要建立與學說的QueryBuilder而不是使用DQL直接利用這個解決方案的查詢。

請注意,我的問題不是獲得頂級用戶組,但技術上這個問題與我的非常相似。我使用帖子(如文章/博客帖子)和添加到帖子的標籤。我需要確定相關帖子的列表(由相同標籤標識)。該列表必須按照相關性進行排序(另一個帖子的標籤越相關)。

這是我PostRepository類的方法:

/** 
* Finds all related posts sorted by relavance 
* (from most important to least important) using 
* the tags of the given post entity. 
* 
* @param Post $post 
* 
* @return POST[] 
*/ 
public function findRelatedPosts(Post $post) { 
    // build query 
    $q = $this->createQueryBuilder('p') 
     ->addSelect('count(t.id) as relevance') 
     ->innerJoin('p.tags', 't') 
     ->where('t.id IN (:tags)') 
     ->setParameter('tags', $post->getTags()) 
     ->andWhere('p.id != :post') 
     ->setParameter('post', $post->getId()) 
     ->addGroupBy('p.id') 
     ->addOrderBy('relevance', 'DESC') 
     ->getQuery(); 

    // execute query and retrieve database result 
    $r = $q->execute(); 

    // result contains arrays, each array contains 
    // the actual post and the relevance value 
    // --> let's extract the post entities and 
    // forget about the relevance, because the 
    // posts are already sorted by relevance 
    $r = array_map(function ($entry) { 
     // first index is the post, second one 
     // is the relevance, just return the post 
     return reset($entry); 
    }, $r); 

    // array of posts 
    return $r; 
} 

謝謝@湯姆Imrei爲您解決。此外,答案#26549597是非常有幫助的。