プログラミング バックエンド

【Sequelize】意図しないサブクエリが発行されてしまうときの対処法(In aggregated query without GROUP BY, expression)

スポンサーリンク

こんにちは!

今回は「意図しないサブクエリが発行されてしまうときの対処法」についてお伝えしたいと思います。

エラーメッセージ:In aggregated query without GROUP BY, expression

僕が業務で実装する中で、Sequelizeでサブクエリを使って取得したいケースがありました。

その際、負荷軽減のためにLIMITを付けたところ、クエリが崩れてしまう現象が起きてしまったのです。
※発行SQLは変わらず
その経験を踏まえてお伝えしたいと思います。

Sequelizeで意図しないサブクエリが発行されてしまうときは、subQuery: falseで治るかもしれない

起きた事象

Sequelize で以下のように記述しました。
親テーブル:room、小テーブル:user

const {fn, col} = db.Sequelize;
exports.getData = (keyword) => {
  const sequelize = require('../utils/getDatabase')(db);
  const dbName = sequelize.models;
  return new Promise((resolve, reject) => {
    dbName.room.findAll({
      attributes: [
        'id',
      ],
      include: [{
        model: dbName.user,
        attributes: [
          [fn('GROUP_CONCAT', col('users.name')), 'name'],
        ],
        required: false,
      }],
      group: ['room.id'],
      limit: 10,
      raw: true,
    }).then((res) => {
      resolve(res);
    }).catch((err) => {
      reject(err);
    });
  });
};

→意図しない場所にサブクエリが生成されてエラーになる
In aggregated query without GROUP BY, expression

発行されたSQLは以下になります。

SELECT
    `room`.*,
    GROUP_CONCAT(`user`.`name`) AS `users.name`,
    GROUP_CONCAT(`user`.`id`) AS `users.id`
FROM
    (
        SELECT
            `room`.`id`,
            `room`.`name`
        FROM
            `room` AS `room`
        GROUP BY
            `room`.`id`
        LIMIT 10
    ) AS `room`
    LEFT OUTER JOIN
        `user` AS `users`
    ON  `room`.`id` = `users`.`room_id`
;

※ちなみにlimitを外すとうまくいきました。

解決策:subQuery: falseを以下のように修正

subQuery: falseというオプションを使います。

上記コードを以下のように修正します。

const {fn, col} = db.Sequelize;
exports.getData = (keyword) => {
  const sequelize = require('../utils/getDatabase')(db);
  const dbName = sequelize.models;
  return new Promise((resolve, reject) => {
    dbName.room.findAll({
      attributes: [
        'id',
      ],
      include: [{
        model: dbName.user,
        attributes: [
          [fn('GROUP_CONCAT', col('users.name')), 'name'],
        ],
        required: false,
      }],
      group: ['room.id'],
      subQuery: false, // ←追加
      limit: 10,
      raw: true,
    }).then((res) => {
      resolve(res);
    }).catch((err) => {
      reject(err);
    });
  });
};

発行されたクエリは以下のようになって、エラーも解消されました!

SELECT
    `room`.`id`,
    `room`.`name`,
    GROUP_CONCAT(`users`.`name`) AS `users.name`
FROM
    `room` AS `room`
    LEFT OUTER JOIN
        `user` AS `users`
    ON  `room`.`id` = `users`.`room_id`
GROUP BY
    `room`.`id`
LIMIT 10
;

 

以上、お疲れさまでした〜🍵

スポンサーリンク

-プログラミング, バックエンド

© 2022 エンジニア×ライフハック Powered by AFFINGER5