Search code examples
phpmysqlsymfonydql

Query with subquery over Symfony on DQL


I have the following situation. I need to make a query, and I do not know how to nest subqueries in DQL.

I have a table of users. Within that table there are Sellers and Representatives. Users have:

---- ID,
---- Name
---- Profile (ROLE_REPRESENTATIVE, ROLE_SELLER)
---- Status (1 = DECLINE | 2 = ON_HOLD | 3 = APPROVED)

Example Users Table:

--------- ID ----------- Name ------------------ PROFILE ------------ STATUS ---- REPRESENTATIVE_ID ----
    ------ 1 -------- Representative_1 ------ ROLE_REPRESENTATIVE ------ 3 ----------- NULL -------------
    ------ 2 -------- seller_1 -------------- ROLE_SELLER -------------- 3 ------------ 1 ---------------
    ------ 3 -------- seller_2 -------------- ROLE_SELLER -------------- 3 ------------ 1 ---------------
    ------ 4 -------- seller_3 -------------- ROLE_SELLER -------------- 2 ------------ 1 ---------------
    ------ 5 -------- Representative_2 ------ ROLE_REPRESENTATIVE ------ 3 ----------- NULL -------------
    ------ 6 -------- Representative_3 ------ ROLE_REPRESENTATIVE ------ 3 ----------- NULL -------------
    ------ 7 -------- seller_4 -------------- ROLE_SELLER -------------- 2 ------------ 5 ---------------
    ------ 8 -------- seller_5 -------------- ROLE_SELLER -------------- 2 ------------ 5 ---------------
    ------ 9 -------- seller_6 -------------- ROLE_SELLER -------------- 2 ------------ 5 ---------------
    ----- 10 -------- seller_7 -------------- ROLE_SELLER -------------- 3 ------------ 1 ---------------
    ----- 11 -------- seller_8 -------------- ROLE_SELLER -------------- 3 ------------ 1 ---------------

Sellers have representatives (representatives) which is a 1-N relationship between Users and Users.

Then, I need to get all the representatives (id + name) and the total of sellers that are not approved (status = 2) (status = 2 = ON_HOLD)

Get Representatives      

SELECT representatives
FROM AppBundle: User representatives
WHERE
    Representatives.profile = 'ROLE_REPRESENTATIVE'
GROUP BY representatives.id
ORDER BY representatives.id DESC

Get sellers "pending" to approve

SELECT sellers
FROM AppBundle: User sellers
WHERE
    Sellers.profile = 'ROLE_SELLER' AND
    Sellers.status = 2
GROUP BY sellers.id
ORDER BY sellers.id DESC

Finally I have to know how to combine this to get:

----- ID ----------- Name --------------- TotalSellersOnHold -----
------ 1 -------- Representative_1 ------------- 40 -----------------
------ 5 -------- Representative_2 ------------- 27 -----------------
------ 6 -------- Representative_3 ------------- 12 -----------------

How could this query be done in 1 single query?


Solution

  • The sql command should be something like that:

    SELECT r.ID, r.Name, COUNT(DISTINCT s.id) as 'TotalSellerOnHold' FROM users r
    INNER JOIN users s ON s.REPRESENTATIVE_ID = r.id
    WHERE r.TYPE = 'ROLE_REPRESENTATIVE'
    AND s.STATUS = 2
    AND s.TYPE = 'ROLE_SELLER'
    GROUP BY r.ID
    ORDER BY r.ID DESC;
    

    In DQL (assuming you are into a custom repository)

    //AppBundle/Repository/MyRepository.php
    public function getAllRepresentativesWithOnSellers()
    {
        $query = $this->createQueryBuilder('r')
            ->select('r.id, r.name')
            ->addSelect('COUNT(DISTINCT s.id)')
            ->innerJoin('AppBundle\Entity\User', 's')
            ->where('r.type = ROLE_REPRESENTATIVE')
            ->andWhere('s.status = 2')
            ->andWhere('s.type = ROLE_SELLER')
            ->groupBy('r.id')
            ->orderBy('r.id', 'desc')
            ->getQuery()
        ;
    
        return $query->getResult();
    }