小编典典

制定复杂的Doctrine2 DQL查询

sql

假设我有一个事件($ event)实例,其中有许多AttendancePerson,则需要获取属于$
event的所有AttendancePerson对象,其中AttendancePerson.person参加了多个事件,该事件的calendar_id与$
event-> calendar_id相匹配,并且AttendancePerson.event.dateTo在上一年结束的位置。

模式减去不相关的列名:

event_attendance_person
    - id
    - event_id
    - person_id
event
    - id
    - calendar_id
    - dateTo
person
    - id
event_calendar
    - id

目的是找到任何给定事件的老成员。在上一年中多次参加共享同一日历的活动的任何活动出席者都是该活动的“老会员”。

我阅读了许多相关的问题。他们都没有帮助。谢谢任何对此有帮助的人。


阅读 135

收藏
2021-04-07

共1个答案

小编典典

对于您的特定要求,即要求从event_attendance_person同一日历的过去一年参加过多个事件的人员到提供的事件的日历,因此在简单的Mysql查询中,您可以联接表以获取每个人的ID的不同事件的计数,即COUNT(DISTINCT e.id)和有条件的对提供的事件ID进行计数让我们说我想让参加事件的人员具有ID,2228因此对于这种起诉案件,您可以这样做,COUNT(CASE WHEN e.id = 2228 THEN 1 END)这将使您为参加此事件的人员的计数为1,为参加事件的人员的计数为0错过该事件,此条件计数的原因是因为我没有使用事件ID的where过滤器,我已经通过使用Haves子句克服了这一问题,并且在过去的一年中,一个简单的where子句是WHERE e.dateTo < DATE_FORMAT(NOW() ,'%Y-01-01 00:00:00')

SELECT p.*,COUNT(DISTINCT e.id) total_events,
COUNT(CASE WHEN e.id = 2228 THEN 1 END) count_event
FROM `event_attendance_person` p
JOIN `event_event` e ON(p.`eventId` = e.id )
JOIN `event_calendar` c ON(e.`calendar` =c.`id`)
WHERE e.`dateTo` < DATE_FORMAT(NOW() ,'%Y-01-01 00:00:00')
GROUP BY p.`personId`
HAVING count_event = 1 AND total_events > 1
ORDER BY total_events DESC

您可以在您的Mysql服务器上测试此查询


现在出现了理论部分,您可以在DQL中将上述查询复制为

$DQL="SELECT p,COUNT(DISTINCT e.id) AS total_events,
 COUNT(CASE WHEN e.id = 2228 THEN 1 END) AS count_event
 FROM NamespaceYourBundle:EventAttendencePerson p
 JOIN p.events e
 JOIN e.calandar c
 WHERE e.dateTo < :dateTo
 GROUP BY p.personId
 HAVING total_events = 1 AND count_event >1
 ORDER BY c DESC
";

对于上述DQL,我假设您已经在实体之间映射了关系,例如下面的上述查询是您的实体中必须存在的强制性关系

  • 加入p.events e 现在p是实体的别名NamespaceYourBundle:EventAttendencePersonEventAttendencePerson实体必须指向您的Event实体,这样ON(p.eventId = e.id )才能实现部分。

  • 加入e.calandar c 现在Event实体必须指向您的Calendar实体才能实现ON(e.calendar =c.id)


然后,您可以通过使用doctrine的paginator类来按以下方式运行DQL

use Doctrine\ORM\Tools\Pagination\Paginator;
$query = $DM->createQuery($DQL)
         ->setParameter('dateTo', date("Y-01-01 00:00:00"))
         ->setFirstResult(0)->setMaxResults(100);
$Persons = new Paginator($query, $fetchJoinCollection = true);
2021-04-07