【问题标题】:Doctrine DQL adds a select column which leads to only_full_group_by errorDoctrine DQL 添加了导致 only_full_group_by 错误的选择列
【发布时间】:2018-04-03 14:13:13
【问题描述】:

我有这个查询,用 DQL 编写:

SELECT
    p
FROM
    Plan p
LEFT JOIN
    p.requests r
WHERE
    p.endsAt > :now
    AND p.organization = :organization
GROUP BY p.id
HAVING SUM(CASE WHEN r.isAccepted IS NULL THEN 0 ELSE r.isAccepted END) = 0
ORDER BY p.id DESC

Wich 绑定到分页器。 在分页器上迭代时,出现以下错误:

SQLSTATE[42000]:语法错误或访问冲突:1055 表达式 #16 的 SELECT 列表不在 GROUP BY 子句中并且包含非聚合 列 'o1_.is_accepted' 没有功能 依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by")。

是由于Doctrine在生成SQL查询时,在select子句中增加了一个列(o1_.is_accepted AS is_accepted_15)(简化后没有分页器的COUNT操作):

SELECT o0_.id AS id_0, o0_.average_hourly_rate AS average_hourly_rate_1, o0_.teacher_to_contact_count AS teacher_to_contact_count_2, o0_.starts_at AS starts_at_3, o0_.ends_at AS ends_at_4, o0_.reference AS reference_5, o0_.bac_plus3 AS bac_plus3_6, o0_.created_at AS created_at_7, o0_.is_paid AS is_paid_8, o0_.paid_at AS paid_at_9, o0_.teacher_who_accepted_count AS teacher_who_accepted_count_10, o0_.unit_price_excluding_vat AS unit_price_excluding_vat_11, o0_.billed_amount AS billed_amount_12, o0_.description AS description_13, min(o1_.is_accepted) AS sclr_14, o1_.is_accepted AS is_accepted_15
FROM organization_teacher_request_plan o0_
LEFT JOIN
    organization_teacher_request o1_
    ON o0_.id = o1_.plan_id
WHERE
    o0_.ends_at > ?
    AND o0_.organization_id = ?
GROUP BY o0_.id
HAVING SUM(CASE WHEN o1_.is_accepted IS NULL THEN 0 ELSE o1_.is_accepted END) = 0

没有 sql 模式“only_full_group_by”也可以正常工作。但我想将此查询修复为迁移到 MySQL 5.7 的最佳实践。

添加MIN(r.isAccepted) 不起作用,因为无论如何添加了o1_.is_accepted 字段。

编辑:这是 DQL 查询的 HAVING SUM(CASE WHEN r.isAccepted IS NULL THEN 0 ELSE r.isAccepted END) = 0 部分,它在 select 子句中添加了相应的字段,一个原则错误?

【问题讨论】:

    标签: mysql doctrine-orm dql


    【解决方案1】:

    我不知道 DQL,也从未使用过它,但语法看起来与 HQL 非常相似,SELECT p 可能返回整个Plan 实体,包括所有列,其中一些没有出现在您的 GROUP BY 子句中。如果您只选择p.id,那么ONLY_FULL_GROUP_BY 错误就会消失:

    SELECT p.id
    FROM Plan p
    LEFT JOIN p.requests r
    ...
    

    【讨论】:

    • 结果我需要整个 Plan 实体,错误与我的 Plan 实体外部的 o1_.is_accepted 字段有关。
    • 不能使用你当前的查询来取回整个计划,在你的服务器使用的模式下它不是有效的 MySQL。您必须再次加入主表。
    【解决方案2】:

    我认为这个查询的问题是使用了HAVING子句来执行过滤,然后需要在SQL中添加字段。

    另一种方法是使用子查询(带有反向查询和 NOT EXISTS 子句)来执行相同的任务,如下所示:

    SELECT
        p
    FROM
        Plan p
    WHERE
        p.endsAt > :now
        AND p.organization = :organization
        AND NOT EXISTS (SELECT r.id FROM $FQCN_OF_REQUEST r WHERE r.id MEMBER OF p.requests AND r.isAccepted = 1)
    ORDER BY p.id DESC
    

    更多信息:https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/dql-doctrine-query-language.html#dql-select-examples

    【讨论】:

      猜你喜欢
      • 2013-01-02
      • 1970-01-01
      • 2014-04-18
      • 1970-01-01
      • 2016-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      相关资源
      最近更新 更多