Php 构造复杂的doctrine2dql查询
假设我有一个Event($Event)实例,其中有许多AttendancePerson,我需要获取属于$Event的所有AttendancePerson对象,其中AttendancePerson.person参与了多个日历id与$Event->calendar_id匹配的事件,并且AttendancePerson.Event.dateTo在上一年结束 架构减去不相关的列名:Php 构造复杂的doctrine2dql查询,php,mysql,sql,symfony,doctrine,Php,Mysql,Sql,Symfony,Doctrine,假设我有一个Event($Event)实例,其中有许多AttendancePerson,我需要获取属于$Event的所有AttendancePerson对象,其中AttendancePerson.person参与了多个日历id与$Event->calendar_id匹配的事件,并且AttendancePerson.Event.dateTo在上一年结束 架构减去不相关的列名: event_attendance_person - id - event_id - person_
event_attendance_person
- id
- event_id
- person_id
event
- id
- calendar_id
- dateTo
person
- id
event_calendar
- id
目的是找到任何给定事件的旧成员。任何在前一年多次参加共享同一日历的活动的活动出席人都是该活动的“老成员”
我通读了许多相关的问题。他们都没帮上忙。感谢所有能在这方面提供帮助的人。为什么活动参与者需要成为自己的对象?像event\u person这样的连接表的多对多关系就足够了吗 任何情况下,假设您的条令实体设置正确,您可能希望将其分为两个单独的DQL查询,第一个查询是获取参加活动的人员列表,然后将这些人员的id列表传递到第二个查询中,该查询执行where person_id IN(person_id)和where event_id!=event.id和calendar.id=event.calendar.id和event.dateTo>计算日期
这两个独立查询的DQL应该很容易编写。对于您的特定要求,即在过去一年中,在同一日历中参加过一次以上活动的
event\u attention\u person
人员可以加入到所提供事件的日历中,因此在纯Mysql查询中,您可以加入您的表,以获得不同事件的计数每个人id的事件数,即COUNT(不同的e.id)
和提供的事件id的条件计数,让我们假设我想获得id2228
的参与事件的人员,因此对于此起诉案例,您可以这样做COUNT(当e.id=2228时,案例1结束)
这将为参加此活动的人员提供计数1,为错过该活动的人员提供计数0,此条件计数的原因是我没有对事件id使用where筛选器,我通过使用having子句克服了这一点,在过去的一年中,一个简单的where子句是where e e.dateTo
假设(人员id,事件id)
在事件出席人数\u人员
中是唯一的
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中(更新列名以匹配示例数据)
event_Attention_person表中还有其他列未列出,因为它们与问题无关。有足够的逻辑围绕着事件出席人认为有自己的课程是值得的。我已经尝试了一个类似于你提出的解决方案,但速度太慢了。您的回答没有考虑到我需要让参加多个活动且日期为<$endOfLastYear且calendarId与$event->calendarId匹配的人员参加活动。这就是为什么他们有资格成为$event的“老成员”。@Justin-所以你已经计算了一组查询,但发现太慢了。好消息。我们可以假设您有所有的索引等,可以考虑添加EvithOyddFieldObjor对象。当某人参加某个活动或活动年份发生变化时,创建或更新这些对象。快速查找旧成员应该很简单。我不确定如何使用Doctrine实现,但在SQL方面,通过连接实现这一点非常简单。请发布示例数据,特别是如何存储
dateTo
。你多久运行一次?每个表中有多少行?这个表上有什么索引?dateTo是datetime Y-m-d H:i:s在event表中会有数千行,在event\u Attention\u person表中会有更多行。为报表运行查询。用户选择一个日期范围,并提取该范围内的任何事件。对于每个活动,我都会在条形图中显示出席人数。该图按类型“旧会员”、“新会员”、“第一次”将出席人数拆分。我需要进行查询以确定任何出席人员的成员类型。上面就是一个例子。所有包含一些示例数据的表$DM
都包含条令对象$DM=$this->getdoctor()->getManager()代码>
$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
";
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);
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
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
$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');