在教义中只加入一行

Posted

技术标签:

【中文标题】在教义中只加入一行【英文标题】:Joining only one row in doctrine 【发布时间】:2018-01-30 09:16:53 【问题描述】:

我有一个包含事件标题和描述的事件表,还有一个 eventInstance 表,其中存储了事件的日期和地点。所以这是一对多的关系:一个事件可以有很多实例。

我现在尝试的是仅选择事件的最新事件实例。在 SQL 中,查询是:

select e.id, e.title, ei.start_date 
from event e 
LEFT join event_instance ei on ei.id = 
(SELECT id FROM event_instance ei where ei.event_id = e.id ORDER BY start_date asc, start_time asc LIMIT 1) 
ORDER BY start_date asc, start_time asc LIMIT 20;

我正在尝试重写 dql 中的 sql 命令。到目前为止,我得到了这个:

SELECT e, ei 
FROM AppBundle:Event e LEFT JOIN e.eventInstances ei WITH ei = 
(SELECT a FROM AppBundle:EventInstance a WHERE a.event = e ORDER BY a.startDate asc, a.startTime asc)

我的问题是,dql 中没有 LIMIT 命令,所以我不能限制子查询给我一个结果。所以我在执行这个查询时遇到的错误是:

SQLSTATE[21000]: Cardinality violation: 7 ERROR: more than one row returned by a subquery used as an expression

有什么方法可以让我完成这项工作吗?

【问题讨论】:

Doctrine Query Language get Max/Latest Row Per Group的可能重复 【参考方案1】:

创建一个子查询,然后在其上设置最大结果。

$subDql = 'SELECT a
           FROM AppBundle:EventInstance a 
           WHERE a.event = e
           ORDER BY a.startDate asc, a.startTime asc';

$subQuery = $this->getEntityManager()
                 ->createQuery($subDql)
                 ->setMaxResults(1)
;

$dql = 'SELECT e, ei FROM AppBundle:Event e
        LEFT JOIN e.eventInstances ei 
        WITH ei = (' .$subQuery . ')'
;

$query = $this->getEntityManager()
              ->createQuery($dql)
              ->setMaxResults($yourOtherLimit)
;

$resultCollection = $query->getResult();

【讨论】:

如果我想为整个查询设置最大结果,这可以正常工作。但我只想为join语句中的子查询设置一个限制(括号中的部分) 好的。我编辑了我的答案。我的代码没有经过测试,所以你可能不得不摆弄它。或者在这里评论异常,看看我们是否可以缩小问题的范围。 不幸的是,这也不起作用。如果我执行您的代码,则会出现错误:Doctrine\ORM\Query 类的对象无法转换为字符串。如果我使用 $subQuery->getDql() 我会收到与以前相同的错误消息。我猜那是因为 setMaxResults 不是 dql 的一部分。我想如果我想让它开始工作,我必须使用本机 sql。不过谢谢你的帮助。 是的,在这一点上,仅使用本机 sql 查询没有什么可失去的。对不起。祝你好运。【参考方案2】:

您的解决方案 (to get latest row per group) 的等效 DQL 将类似于

SELECT e,a 
FROM AppBundle:Event e
    JOIN e.eventInstances a
    LEFT JOIN AppBundle\Entity\Score b 
    WITH a.event = b.event 
    AND a.startDate < b.startDate
    AND a.startTime < b.startTime
WHERE b.event IS NULL
ORDER BY a.startTime DESC

SELECT e,a 
FROM AppBundle:Event e
    JOIN e.eventInstances a
    LEFT JOIN AppBundle\Entity\Score b 
    WITH a.event = b.event 
    AND a.startDate = b.startDate
    AND a.startTime < b.startTime
WHERE b.event IS NULL
ORDER BY a.startTime DESC

【讨论】:

以上是关于在教义中只加入一行的主要内容,如果未能解决你的问题,请参考以下文章

教义:加入一对一的关系

如何使用mysql join从最右边的表中只返回一行

SQL 在 select 子查询中只返回一行或 null

如何从子查询中只获取一行?

在 extjs 网格中只为一行添加组合框

LOAD DATA LOCAL INFILE 在 MySQL 中只导入一行