简体   繁体   中英

Doctrine QueryBuilder > Working with ManyToMany relationships

I have been struggling with this issue for a while and all relevant topics does not match my specific needs. I am building a "dashboard" that provides system oversight on a wide range of entities. For obvious reasons I would like to keep my queries as few and as efficient as possible. Therefor I am trying to limit my queries to 1 per entity where I retrieve all the relevant info.

My problem comes in when I need to extract specific data from ManyToMany (or OneToMany) relational entities.

For example, in the following case I am trying to find the amount of accounts that do not have any invoices linked to them.

    $qb = $this->getDoctrine()->getManager()->createQueryBuilder();
    $qb->select(array(
        'COUNT(account) as totalAccounts', 
        'SUM(account.active) as activeAccounts',
        'SUM(account.approved) as approvedAccounts',
        'SUM(account.reverted) as revertedAccounts',
        'SUM(account.approvalRequested) as pendingApprovalAccounts',
        "SUM(CASE WHEN COUNT(account.invoices) = 0 THEN 1 ELSE 0 END) as testAccounts"
    ))
    ->from('AppBundle:Account', 'account');

I receive a the following error: QueryException: [Semantical Error] line 0, col 252 near 'invoices) = 0': Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected.

In the following example I am trying to find the number of users that have unpaid invoices attached to them. I tried a different approach by joining user.invoices.

    $qb = $this->getDoctrine()->getManager()->createQueryBuilder();
    $qb->select(array(
        'COUNT(user) as totalUsers', 
        'SUM(user.active) as activeUsers',
        "SUM(CASE WHEN user.userType = 'MONTHLY' AND user.active = true THEN 1 ELSE 0 END) as monthlyUsers",
        "SUM(CASE WHEN user.userType = 'PAYG' AND user.active = true THEN 1 ELSE 0 END) as paygUsers",
        "SUM(CASE WHEN user.noticeType = 'SWITCH' AND user.active = true THEN 1 ELSE 0 END) as noticeUsersPayg",
        "SUM(CASE WHEN user.noticeType = 'DISABLE' AND user.active = true THEN 1 ELSE 0 END) as noticeUsersDisable",
        "SUM(CASE WHEN SUM(CASE WHEN invoices.datePaid is null THEN 1 ELSE 0 END) > 0 THEN 1 ELSE 0 END) as suspendedUsers",
    ))
    ->from('AppBundle:User', 'user')
    ->leftJoin('user.invoices', 'invoices');

In this case I get the error: SQLSTATE[HY000]: General error: 1111 Invalid use of group function

I can easily build the right query with all the necessary SELECT subqueries in SQL, but I am trying to do this the right way by using QueryBuilder. QueryBuilder also does not seem to accept or allow SELECT subqueries. I know that I am probably doing a few (or many) things wrong, and that is why I am posting this question. I think others can greatly benefit if this question is answered properly, as queries where relational entities affects returned data is an issue that we have all encountered and I could not find any proper content that addresses this matter.

You are mostly fighting the ORM now, and I think this is one of the cases where you are better of using native queries. You are basically returning scalar values for reporting only, there are not that many advantages of using the ORM for that.

See http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM