mysql - 查询匹配()导致重复行和不同()不起作用
问题描述
我正在尝试通过关联表发票上的字段过滤一个表付款。
在查询对象上使用该函数matching()
可以正确过滤,但会导致重复行。似乎解决方案正在使用distinct()
,但调用distinct(Payments.id)
会导致无效查询。我在控制器操作中执行以下操作。
$conditions = [
'Payments.is_deleted =' => false
];
$args = [
'conditions' => $conditions,
'contain' => ['Invoices', 'Invoices.Clients'],
];
$payments = $this->Payments->find('all', $args);
if($issuer) {
// This causes duplicate rows
$payments->matching('Invoices', function ($q) use ($issuer) {
return $q->where(['Invoices.issuer_id' => $issuer['id']]);
});
// $payments->distinct('Payments.id'); // Causes a mysql error
}
我是否正确地认为这distinct()
是我需要的,如果是的话,有什么想法使它起作用吗?
取消注释上面的行时,我收到以下 mysql 错误:
错误:SQLSTATE[42000]:语法错误或访问冲突:1055 SELECT 列表的表达式 #8 不在 GROUP BY 子句中,并且包含在功能上不依赖于 GROUP BY 子句中的列的非聚合列“InvoicesPayments.id”;这与 sql_mode=only_full_group_by 不兼容
完整查询:
SELECT
PAYMENTS.ID AS `PAYMENTS__ID`,
PAYMENTS.CREATED AS `PAYMENTS__CREATED`,
PAYMENTS.MODIFIED AS `PAYMENTS__MODIFIED`,
PAYMENTS.DATE_REGISTERED AS `PAYMENTS__DATE_REGISTERED`,
PAYMENTS.USER_ID AS `PAYMENTS__USER_ID`,
PAYMENTS.AMOUNT AS `PAYMENTS__AMOUNT`,
PAYMENTS.IS_DELETED AS `PAYMENTS__IS_DELETED`,
INVOICESPAYMENTS.ID AS `INVOICESPAYMENTS__ID`,
INVOICESPAYMENTS.INVOICE_ID AS `INVOICESPAYMENTS__INVOICE_ID`,
INVOICESPAYMENTS.PAYMENT_ID AS `INVOICESPAYMENTS__PAYMENT_ID`,
INVOICESPAYMENTS.PART_AMOUNT AS `INVOICESPAYMENTS__PART_AMOUNT`,
INVOICES.ID AS `INVOICES__ID`,
INVOICES.CREATED AS `INVOICES__CREATED`,
INVOICES.MODIFIED AS `INVOICES__MODIFIED`,
INVOICES.IS_PAID AS `INVOICES__IS_PAID`,
INVOICES.IS_DELETED AS `INVOICES__IS_DELETED`,
INVOICES.CLIENT_ID AS `INVOICES__CLIENT_ID`,
INVOICES.ISSUER_ID AS `INVOICES__ISSUER_ID`,
INVOICES.NUMBER AS `INVOICES__NUMBER`,
INVOICES.SUBTOTAL AS `INVOICES__SUBTOTAL`,
INVOICES.TOTAL AS `INVOICES__TOTAL`,
INVOICES.DATE_REGISTERED AS `INVOICES__DATE_REGISTERED`,
INVOICES.CURRENCY AS `INVOICES__CURRENCY`,
INVOICES.RECEIVER_NAME AS `INVOICES__RECEIVER_NAME`,
INVOICES.RECEIVER_RFC AS `INVOICES__RECEIVER_RFC`,
INVOICES.EMAIL_SENDER AS `INVOICES__EMAIL_SENDER`,
INVOICES.PDF_PATH AS `INVOICES__PDF_PATH`
FROM
PAYMENTS PAYMENTS
INNER JOIN
INVOICES_PAYMENTS INVOICESPAYMENTS
ON PAYMENTS.ID = (
INVOICESPAYMENTS.PAYMENT_ID
)
INNER JOIN
INVOICES INVOICES
ON (
INVOICES.ISSUER_ID = :C0
AND INVOICES.ID = (
INVOICESPAYMENTS.INVOICE_ID
)
)
WHERE
(
PAYMENTS.IS_DELETED = :C1
AND PAYMENTS.DATE_REGISTERED >= :C2
AND PAYMENTS.DATE_REGISTERED <= :C3
)
GROUP BY
PAYMENT_ID
ORDER BY
PAYMENTS.DATE_REGISTERED ASC
解决方案
这种行为是预期的,因为匹配将使用INNER
连接,是的,分组是避免重复的方式:
由于此函数将创建一个 INNER JOIN,因此您可能需要考虑在 find 查询上调用 distinct,因为如果您的条件尚未排除它们,您可能会得到重复的行。例如,当同一用户对一篇文章多次评论时,可能就是这种情况。
Cookbook > Database Access & ORM > Query Builder > Loading Associations > 按关联数据过滤
如错误消息所述,您的 MySQL 服务器配置为使用严格only_full_group_by
模式,您的查询无效。您可以禁用Akash prajapati 提到的严格模式(这可能会带来自己的问题,因为 MySQL 可以随机选择一个组的值),或者您可以更改查询方式以符合要求到严格模式。
在您需要对主键进行分组的情况下,您可以简单地切换到使用innerJoinWith()
,不像matching()
这不会将该关联的任何字段添加到SELECT
列表中,并且在严格模式下应该没问题,因为其他一切都依赖于功能:
如果您要对会破坏功能依赖性检测的键进行分组,解决该问题的一种方法可能是例如使用子查询进行过滤,只选择该键,类似于以下内容:
$conditions = [
'Payments.is_deleted =' => false
];
$payments = $this->Payments
->find()
->contain(['Invoices.Clients']);
if($issuer) {
$matcherQuery = $this->Payments
->find()
->select(['Payments.some_other_field'])
->where($conditions)
->matching('Invoices', function ($q) use ($issuer) {
return $q->where(['Invoices.issuer_id' => $issuer['id']]);
})
->distinct('Payments.some_other_field');
$payments->where([
'Payments.some_other_field IN' => $matcherQuery
]);
} else {
$payments->where($conditions);
}
这将产生与此类似的查询,然后外部查询可以选择您想要的所有字段:
SELECT
...
FROM
payments
WHERE
payments.some_other_field IN (
SELECT
payments.some_other_field
FROM
payments
INNER JOIN
invoices_payments ON
payments.id = invoices_payments.payment_id
INNER JOIN
invoices ON
invoices.issuer_id = ...
AND
invoices.id = invoices_payments.invoice_id
WHERE
payments.is_deleted = ...
GROUP BY
payments.some_other_field
)
推荐阅读
- javascript - 如何在 HTML 中引用当前 URL?
- netlogo - 如何以相同(非随机)的顺序从 NetLogo 代理集中检索多个变量?
- c++ - 与 QMainWindow 的 GUI 命令交互时,QDockWidget 无法正确调整大小
- python - TypeError:列表索引必须是整数或切片,而不是元组,我很新并且很困惑为什么我的列表列表不起作用
- java - 值更新不是 scala.collection.immutable.Map 的成员
- reactjs - 在 React 组件中使用常量
- node.js - nodejs套接字挂断超时
- mysql - MySQL - 搜索 JSON 数据列
- asp.net - 下拉菜单在 datagridview asp.net 中不起作用
- cypress - 赛普拉斯:有没有办法检查元素的不可见性