制定复杂的Doctrine2 DQL查询

时间:2014-08-27 04:00:28

标签: php mysql sql symfony doctrine

鉴于我有一个具有许多AttendancePerson的Event($ event)实例,我需要获取属于$ 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

目的是找到任何特定事件的旧成员。参加过去一年多次共享同一日历的活动的参加活动的人是“老会员”#34;事件。

我读了许多相关问题。他们都没有帮助。感谢能够为您提供帮助的任何人。

3 个答案:

答案 0 :(得分:1)

根据您的具体要求,让event_attendance_person人在同一日历的过去一年中参加过多于1次活动的人到所提供活动的日历,所以在普通的Mysql查询中,您可以加入您的表格,获得不同的数量每个人身份的事件ID COUNT(DISTINCT e.id)以及所提供事件ID的条件计数让我说我想让那些参加了身份2228事件的人参加这样的起诉案件,你可以这样做{ {1}}这会给你参加此活动的人的计数1和错过该事件的人的0,这个条件计数的原因是因为我没有使用事件id的过滤器我通过使用克服了这个有条款和过去一年的简单where子句是COUNT(CASE WHEN e.id = 2228 THEN 1 END)

WHERE e.dateTo < DATE_FORMAT(NOW() ,'%Y-01-01 00:00:00')

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


现在,您可以在DQL中将查询复制上面的学说部分作为

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

对于上面的DQL,我假设你已经在你的实体之间映射了你的关系,就像上面的查询一样,这些关系必须存在于你的实体中

  • 加入p.events e 现在p是实体$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 "; 的别名,NamespaceYourBundle:EventAttendencePerson实体必须指向您的EventAttendencePerson实体,以便开启Event部分可以实现

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


然后您可以使用doctrine的paginator类

运行您的DQL,如下所示
ON(e.calendar =c.id)

答案 1 :(得分:1)

假设(person_id,event_id)event_attendance_person是唯一的。

1 get all persons belonging to given event
2 for each person get all their other events having the same calendar id and some end date
3 group by person id
4 filter by persons having more than 1 other event

在SQL中(更新的列名称以匹配示例数据)

select p.id
from event_event e
join event_attendance_person eap on eap.eventId = e.id
join person p on eap.personId = p.id
join event_attendance_person eap2 on eap2.personId = p.id
join event_event e2 on e2.id = eap2.eventId
where e.id = 2230
and e2.id <> 2230
and e2.calendar = e.calendar
and e2.dateTo between '2013-01-01' and '2014-12-31'
group by p.id
having count(e2.id) > 1

使用QueryBuilder

$qb->select('p')
    ->from('MyBundleNameSpace\Entity\Event', 'e')
    ->innerJoin('e.person','p')
    ->innerJoin('p.event','e2')
    ->where('IDENTITY(e) = :event_id')
    ->andWhere('IDENTITY(e2) != :event_id')
    ->andWhere('IDENTITY(e2.calendar) = IDENTITY(e.calendar)')
    ->andWhere('e2.dateTo BETWEEN :start AND :end')
    ->groupBy('p')
    ->having('count(e2.id) > 1')
    ->setParameter('event_id',$event->getId())
    ->setParameter('start','2012-01-1')
    ->setParameter('end','2013-12-31');

答案 2 :(得分:0)

为什么event_attendance_person需要成为它自己的对象?与event_person这样的连接表不会有多对多的关系吗?

假设您正确设置了您的学说实体,您可能希望将其拆分为两个单独的DQL查询,第一个查询是您获取参加活动的人员列表然后传递ID的地方第二个查询中的那些人的列表,其中person_id IN(person_ids)和WHERE event_id!= event.id AND calendar.id = event.calendar.id AND event.dateTo&gt; calculated_date

这两个单独查询的DQL应该很容易编写。