在 Cakephp 4 中使用 contains()、order() 和 limit() 进行查询时出现问题
我有以下两个关联:
AgendaDates hasOne
ImageDescriptive
AgendaDates hasMany
Photos
当我执行此查询时:
$dates = $this->AgendaDates
->find()
->order(['AgendaDates.date' => 'ASC'])
->contain(['ImageDescriptive' => function ($q) { // AgendaDates hasOne ImageDescriptive
return $q->find('translations');
}])
->limit(2);
出现以下错误:
SQLSTATE[42000]:语法错误或访问冲突:1055 ORDER BY 子句的表达式 #1 不在 GROUP BY 子句中并且包含非聚合列“brigitte Patient.AgendaDates.date”在功能上不依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by 不兼容
返回错误的 SQL 查询是:
SELECT
FichiersI18n.id AS FichiersI18n__id,
FichiersI18n.locale AS FichiersI18n__locale,
FichiersI18n.model AS FichiersI18n__model,
FichiersI18n.foreign_key AS FichiersI18n__foreign_key,
FichiersI18n.field AS FichiersI18n__field,
FichiersI18n.content AS FichiersI18n__content
FROM
fichiers_i18n FichiersI18n
INNER JOIN (
SELECT
(ImageDescriptive.id)
FROM
agenda_dates AgendaDates
LEFT JOIN fichiers ImageDescriptive ON (
ImageDescriptive.model = 'AgendaDates'
AND ImageDescriptive.field = 'image_descriptive'
AND AgendaDates.id = ImageDescriptive.foreign_key
)
GROUP BY
ImageDescriptive.id
ORDER BY
AgendaDates.date ASC
LIMIT
2
) ImageDescriptive ON FichiersI18n.foreign_key = ImageDescriptive.id
WHERE
FichiersI18n.model = 'Fichiers'
奇怪的是,当我做同样的事情但使用照片时(通过 hasMany
而不是 < 链接到 AgendaDates) code>hasOne) :
$dates = $this->AgendaDates
->find()
->order(['AgendaDates.date' => 'ASC'])
->contain(['Photos' => function ($q) { // AgendaDates hasMany Photos
return $q->find('translations');
}])
->limit(2);
我没有错误并且查询看起来像这样:
SELECT
FichiersI18n.id AS FichiersI18n__id,
FichiersI18n.locale AS FichiersI18n__locale,
FichiersI18n.model AS FichiersI18n__model,
FichiersI18n.foreign_key AS FichiersI18n__foreign_key,
FichiersI18n.field AS FichiersI18n__field,
FichiersI18n.content AS FichiersI18n__content
FROM
fichiers_i18n FichiersI18n
INNER JOIN (
SELECT
(Photos.id)
FROM
fichiers Photos
WHERE
(
Photos.model = 'AgendaDates'
AND Photos.field = 'photos'
AND Photos.foreign_key in (5, 3)
)
GROUP BY
Photos.id
) Photos ON FichiersI18n.foreign_key = Photos.id
WHERE
FichiersI18n.model = 'Fichiers'
我真的不明白为什么我的 cakephp 查询在以下情况下会抛出错误hasOne
关联,但在 hasMany
关联的情况下则不然?
I have the two following associations :
AgendaDates hasOne
ImageDescriptive
AgendaDates hasMany
Photos
When I do this query :
$dates = $this->AgendaDates
->find()
->order(['AgendaDates.date' => 'ASC'])
->contain(['ImageDescriptive' => function ($q) { // AgendaDates hasOne ImageDescriptive
return $q->find('translations');
}])
->limit(2);
I have the following error :
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'brigittepatient.AgendaDates.date' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
The SQL query that returns an error is :
SELECT
FichiersI18n.id AS FichiersI18n__id,
FichiersI18n.locale AS FichiersI18n__locale,
FichiersI18n.model AS FichiersI18n__model,
FichiersI18n.foreign_key AS FichiersI18n__foreign_key,
FichiersI18n.field AS FichiersI18n__field,
FichiersI18n.content AS FichiersI18n__content
FROM
fichiers_i18n FichiersI18n
INNER JOIN (
SELECT
(ImageDescriptive.id)
FROM
agenda_dates AgendaDates
LEFT JOIN fichiers ImageDescriptive ON (
ImageDescriptive.model = 'AgendaDates'
AND ImageDescriptive.field = 'image_descriptive'
AND AgendaDates.id = ImageDescriptive.foreign_key
)
GROUP BY
ImageDescriptive.id
ORDER BY
AgendaDates.date ASC
LIMIT
2
) ImageDescriptive ON FichiersI18n.foreign_key = ImageDescriptive.id
WHERE
FichiersI18n.model = 'Fichiers'
The strange thing is that when I do the same thing but with Photos (linked to AgendaDates by hasMany
instead of hasOne
) :
$dates = $this->AgendaDates
->find()
->order(['AgendaDates.date' => 'ASC'])
->contain(['Photos' => function ($q) { // AgendaDates hasMany Photos
return $q->find('translations');
}])
->limit(2);
I have no error and the query looks like that :
SELECT
FichiersI18n.id AS FichiersI18n__id,
FichiersI18n.locale AS FichiersI18n__locale,
FichiersI18n.model AS FichiersI18n__model,
FichiersI18n.foreign_key AS FichiersI18n__foreign_key,
FichiersI18n.field AS FichiersI18n__field,
FichiersI18n.content AS FichiersI18n__content
FROM
fichiers_i18n FichiersI18n
INNER JOIN (
SELECT
(Photos.id)
FROM
fichiers Photos
WHERE
(
Photos.model = 'AgendaDates'
AND Photos.field = 'photos'
AND Photos.foreign_key in (5, 3)
)
GROUP BY
Photos.id
) Photos ON FichiersI18n.foreign_key = Photos.id
WHERE
FichiersI18n.model = 'Fichiers'
I really don't understand why my cakephp query throws an error in the case of hasOne
association but not in the case of hasMany
association ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
严格分组
only_full_group_by
模式要求SELECT
、HAVING
和ORDER BY
中的所有字段必须是功能相关的 (列a
唯一确定列b
),或聚合。分组时,组中列的所有值不一定都相等,想象一下
Articles hasMany Comments
关系,如果您加入Comments
并按Articles 分组.id
,Articles
的所有列都可以通过id
主键列确定,而Comments
的列则不能,有可能有多个不同的每个Article.id
的Comments
列值,如下所示:如果你有这样的结果,那么 MySQL 将不知道选择两个不同的
Comments.created
值中的哪一个当要求按组排序时,从该组中删除,因此发出可能产生此类结果的查询将引发错误。当严格分组模式被禁用时,MySQL将被允许从组中基本上随机地选择一个值,这使得结果不可预测,这可能是一个问题。使用聚合可以解决这个问题,例如
MIN(Comments.created)
使用组中的最小日期值。您可以在文档中以及通常在互联网上找到有关该主题的更多信息:
hasMany 与 hasOne
您的两个查询生成不同的 SQL,
hasMany
关联始终在单独的查询中检索,那就是那里您正在调用translations
查找器,这是一个单独的查询,其中没有发生连接、排序和限制,因此翻译分组不会导致任何问题,因为只有一个字段用于分组涉及。hasOne
关联默认使用联接,因此是单个查询,因此您在该单个查询上调用translations
查找器,即您要进行排序的查询和限制,这就是翻译分组与引用组中字段的顺序之间的冲突的根源。tl;dr
通过对翻译行为使用
select
策略应该可以避免此问题,然后使用查询的主键而不是应用分组的子查询来获取翻译:
ImageDescriptive
关联的INNER
联接也可能解决该问题(即查询可能生成的多个null
值是函数依赖问题的根源),但它当然会改变涉及null
值时查询记录的方式。Strict Grouping
The
only_full_group_by
mode requires that all fields inSELECT
,HAVING
andORDER BY
must be either functionally dependent (columna
uniquely determines columnb
), or aggregates.When grouping, not all values for a column in a group will necessarily be equal, imagine an
Articles hasMany Comments
relation, if you join inComments
and group byArticles.id
, all columns ofArticles
can be determined by theid
primary key column, the columns ofComments
however cannot, there could be multiple differentComments
column values perArticle.id
, something like this:If you had such results, then MySQL wouldn't know which of the two different
Comments.created
values to pick from the group when asked to order by it, hence issuing a query that could produce such a result will throw an error.When strict group by mode is disabled, then MySQL would be allowed to pick a value from the group basically at random, which makes the results unpredictable, which can be a problem. Using an aggegrate can fix that, for example
MIN(Comments.created)
to use the smallest date value from the groups.You can find more on that topic in the docs, and generally all over the internet:
hasMany vs hasOne
Your two queries produce different SQL,
hasMany
associations are always retrieved in a separate query, that is where you're calling thetranslations
finder on, a separate query where no joining, ordering and limiting is happening, hence the grouping for the translations will not cause any problems since only the one field that is used for grouping is involved.hasOne
association are using joins by default, so a single query, hence here you're calling thetranslations
finder on that single query, the one where you're doing the sorting and limiting, and that's where the clash between the grouping for the translations and the ordering that references a field from the group stems from.tl;dr
It should be possible to avoid this problem by using the
select
strategy for the translate behavior, which will then obtain the translations using the queried primary keys instead of a subquery where grouping is applied:Using an
INNER
join for theImageDescriptive
association might possibly also fix the problem (that is in case the possible multiplenull
values that the query could produce are the source of the functional dependency problem), but it would of course change how records are queried whennull
values are involved.