简体   繁体   中英

How to use MAX function result in DQL condition?

Here's my db schema:

| User  |      | View     |
*-------*      *----------*
| id    |      | id       |
               | date     |
| Movie |      | movie_id |
*-------*      | user_id  |
| id    |
| title |      | Comment   |
| slug  |      *-----------*
| cover |      | id        |
               | createdAt |
               | view_id   |
               | user_id   |

What I'm trying to achieve is to select movies that have at least one view older than any comment posted on a movie for a specific user, or that have never been commented by this user.

I'm using Doctrine 2, and here's what I've done so far:

$this->createQueryBuilder('movie')
    ->select('DISTINCT movie.id', 'movie.title', 'movie.slug', 'movie.cover')
    ->addSelect('MAX(view.date) as lastViewedOn')
    ->addSelect('MAX(comment.createdAt) as lastCommentedOn')
    ->innerJoin('movie.views', 'view', 'WITH', 'view.user = :user')
    ->leftJoin('movie.comments', 'comment', 'WITH', 'comment.author = :user')
    ->andWhere(
        $qb->expr()->orX('lastCommentedOn IS NULL', 'lastViewedOn > lastCommentedOn')
    )
    ->orderBy('lastViewedOn', 'DESC')
    ->setParameter('user', $user)
    ->getQuery()
    ->getScalarResult()
;

Problem is that this request throws an exception:

QueryException: [Semantical Error] line 0, col 410 near 'lastCommentedOn': Error: 'lastCommentedOn' does not point to a Class.

and I don't really see why...

Thanks for your enlightenment.

I've ended with this plain SQL solution:

        SELECT m.id, m.title, m.slug, m.cover, v.maxDate
            FROM movie m
            INNER JOIN (
                SELECT movie_id, MAX(date) maxDate
                FROM view
                WHERE user_id = :user
                GROUP BY movie_id
            ) v ON m.id = v.movie_id
            LEFT JOIN (
                SELECT id, movie_id, MAX(created_at) maxDate
                FROM comment
                WHERE author_id = :user
                GROUP BY movie_id
            ) c ON c.movie_id = m.id
        WHERE m.online_on <= :from AND (m.offline_on IS NULL OR m.offline_on > :from)
        AND (c.id IS NULL OR v.maxDate > c.maxDate)
        ORDER BY v.maxDate DESC

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