Вот моя схема БД:
| User | | View |
*-------* *----------*
| id | | id |
| date |
| Movie | | movie_id |
*-------* | user_id |
| id |
| title | | Comment |
| slug | *-----------*
| cover | | id |
| createdAt |
| view_id |
| user_id |
То, чего я пытаюсь добиться, — это выбрать фильмы, которые по крайней мере на один просмотр старше любого комментария, размещенного в фильме для определенного пользователя, или который никогда не комментировал этот пользователь.
Я использую Doctrine 2, и вот что я сделал до сих пор:
$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()
;
Проблема в том, что этот запрос вызывает исключение:
QueryException: [Semantical Error] line 0, col 410 near 'lastCommentedOn': Error: 'lastCommentedOn' does not point to a Class.
и я не понимаю, почему …
Спасибо за ваше просвещение.
Я закончил с этим простым решением SQL:
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
Других решений пока нет …