Sequelize ORM 在选择中添加主键列,虽然我排除了它

Sun*_*S.M 5 mysql node.js sequelize.js

我已经通过sequelize准备了一个查询,它通过关联hasOne、聚合函数SUM()和Group By子句获取记录,但是sequelize查询自动添加了目标表主键列,并且该列导致group by子句错误。

这是我的节点函数,它从服务获取数据。

exports.getCustomerByManagerId = async (userId, limit, offset) => {
  const customers = await models.Customer.findAndCountAll({
    where: { account_manager_id: userId },
    include: [
      { model: models.UserProfile, as: 'accountmanager', attributes: userProfileSanitizer.sanitizeuserProfile() },
      {
        model: models.Task,
        as: 'customertask',
        attributes: [
          [sequelize.literal('SUM(IF(customertask.status = 1, 1, 0))'), 'todo'],
          [sequelize.literal('SUM(IF(customertask.status = 2, 1, 0))'), 'pendingTask'],
          [sequelize.literal('SUM(IF(customertask.status = 3, 1, 0))'), 'completeTask'],
          [sequelize.literal('COUNT(customertask.id)'), 'totalTask']
        ]
      }
    ],
    group: ['`customer`.`customer_id`'],
    order: [
      ['createdAt', 'DESC']
    ],
    limit,
    offset
  });
Run Code Online (Sandbox Code Playgroud)

并执行续集查询生成结果查询 AS :

SELECT `customer`.`customer_id`, `customer`.`userId`, `customer`.`name`, `customer`.`account_manager_id`, `customer`.`start_date`, `customer`.`renewal_date`, `customer`.`customer_type`, 
`customer`.`SKU`, `customer`.`variation`, `customer`.`similar`, `customer`.`setCost`, `customer`.`SKUCost`, `customer`.`variationCost`, `customer`.`similarCost`, 
`customer`.`actual_monthly_cost`, `customer`.`address1`, `customer`.`address2`, `customer`.`city`, `customer`.`state`, `customer`.`category`, `customer`.`createdAt`, 
`customer`.`updatedAt`, `accountmanager`.`userId` AS `accountmanager.userId`, `accountmanager`.`firstName` AS `accountmanager.firstName`, `accountmanager`.`lastName` 
AS `accountmanager.lastName`, `accountmanager`.`isTermsofService` AS `accountmanager.isTermsofService`, 
`customertask`.`id` AS `customertask.id`,
SUM(IF(customertask.status = 1, 1, 0)) AS `customertask.todo`, 
SUM(IF(customertask.status = 2, 1, 0)) AS `customertask.pendingTask`, 
SUM(IF(customertask.status = 3, 1, 0)) AS `customertask.completeTask`, 
COUNT(customertask.customer_id) AS `customertask.totalTask` 
FROM `customer` AS `customer` 
LEFT OUTER JOIN `user_profiles` AS `accountmanager` ON `customer`.`account_manager_id` = `accountmanager`.`userId` 
LEFT OUTER JOIN `task` AS `customertask` ON `customer`.`customer_id` = `customertask`.`customer_id` 
WHERE `customer`.`account_manager_id` = 1 
GROUP BY `customer`.`customer_id`
ORDER BY `customer`.`createdAt` DESC LIMIT 0, 10;
Run Code Online (Sandbox Code Playgroud)

这是由sequelize 添加的,会导致错误customertaskidAS customertask.id,当我删除这一行并在 mysql 工作台编辑器中执行查询时,它就可以工作

错误 AS:错误代码:1055。SELECT 列表的表达式 #27 不在 GROUP BY 子句中,并且包含非聚合列“DBName.customertask.id”,该列在功能上不依赖于 GROUP BY 子句中的列

小智 6

添加 raw:true 会有所帮助,并且默认情况下不会添加主键。


Ank*_*nkh 0

我会在序言中说,我不知道这是否是 not 的解决方案,但在评论中写得太多了。

您是否尝试过明确排除该id字段customertask,使其不是选定的属性?例如

exports.getCustomerByManagerId = async (userId, limit, offset) =>
{
    const customers = await models.Customer.findAndCountAll({
        where: { account_manager_id: userId },
        include: [
            { model: models.UserProfile, as: 'accountmanager', attributes: userProfileSanitizer.sanitizeuserProfile() },
            {
                model: models.Task,
                as: 'customertask',
                attributes: {
                    include: [
                        [ sequelize.literal('SUM(IF(customertask.status = 1, 1, 0))'), 'todo' ],
                        [ sequelize.literal('SUM(IF(customertask.status = 2, 1, 0))'), 'pendingTask' ],
                        [ sequelize.literal('SUM(IF(customertask.status = 3, 1, 0))'), 'completeTask' ],
                        [ sequelize.literal('COUNT(customertask.id)'), 'totalTask' ]
                    ],
                    exclude: [ 'id' ] // <---------- exclude the id
                }
            }
        ],
        group: [ '`customer`.`customer_id`' ],
        order: [
            [ 'createdAt', 'DESC' ]
        ],
        limit,
        offset
    });
};
Run Code Online (Sandbox Code Playgroud)