【问题标题】:How to get a distinct count with sequelize?如何通过 sequelize 获得不同的计数?
【发布时间】:2014-03-25 18:27:18
【问题描述】:

我正在尝试使用 sequelize 获取特定列的不同计数。我最初的尝试是使用我的模型的“计数”方法,但看起来这不可能。

需要 DISTINCT 功能,因为我正在加入其他表并根据相关表过滤父级的行。

这是我想要的查询:

SELECT COUNT(DISTINCT Product.id) as `count` 
FROM `Product` 
LEFT OUTER JOIN `Vendor` AS `vendor` ON `vendor`.`id` = `Product`.`vendorId` 
WHERE (`vendor`.`isEnabled`=true );

对我的产品模型使用以下查询:

Product.count({
        include: [{model: models.Vendor, as: 'vendor'}],
        where: [{ 'vendor.isEnabled' : true }]
    })

生成以下查询:

SELECT COUNT(*) as `count` 
FROM `Product` 
LEFT OUTER JOIN `Vendor` AS `vendor` ON `vendor`.`id` = `Product`.`vendorId` 
WHERE (`vendor`.`isEnabled`=true );

【问题讨论】:

  • 为什么不直接使用存储过程并调用它呢?根据这个 changelog (sequelizejs.com/changelog/v1-6-0) sequelize 支持存储过程。然后,您可以以最适合您需求的方式编写查询,并针对您正在使用的数据库对其进行优化。
  • 这可能是一个有效的解决方案,您是说没有其他方法可以在计数操作中包含 DISTINCT 吗?
  • 我不知道任何其他方式,但其他人可能对如何实现它有想法。通常,出于诸如此类的原因,我尝试对所有与数据库相关的代码使用存储过程。无论我碰巧使用什么前端技术,我都会使用这种方法。真正令人高兴的是,您可以在针对您的数据库使用不同的前端技术时重复使用该存储过程。
  • @Adam 你怎么这么喜欢 DISTINCT 和 Sequelize?
  • @JoshC 因为我喜欢在人群中脱颖而出。我是一个偶像破坏者。

标签: sequelize.js


【解决方案1】:

更新:新版本

现在有单独的 distinctcol 选项。 The docs for distinct状态:

在主键或 options.col 上应用 COUNT(DISTINCT(col))。

你想要一些类似的东西:

MyModel.count({
  include: ...,
  where: ...,
  distinct: true,
  col: 'Product.id'
})
.then(function(count) {
    // count is an integer
});

原帖

(正如 cmets 中提到的,自从我的原始帖子以来,情况发生了变化,所以你可能想忽略这部分。)

查看Model.count method in lib/model.js 并跟踪一些代码后,我发现在使用Model.count 时,您可以将MYSQL 支持的任何类型的聚合函数参数添加到您的选项对象中。以下代码将为您提供MyModelsomeColumn 中不同值的数量:

MyModel.count({distinct: 'someColumn', where: {...}})
.then(function(count) {
    // count is an integer
});

该代码有效地生成了这种查询:SELECT COUNT(args) FROM MyModel WHERE ...,其中args 是选项对象中未保留的所有属性(例如DISTINCTLIMIT 等)。

【讨论】:

  • 其实distinct参数是一个布尔参数,它只表示是否应该使用distinct。不同的计数始终应用于模型的主键,因此此解决方案将无法相应地工作,至少不适用于当前的 sequelize 版本。
【解决方案2】:

现在 Sequelize 版本 1.7.0+ 似乎支持此功能。

模型的 countfindAndCountAll 方法将为您提供父模型的“真实”或“不同”计数。

【讨论】:

  • 我最近才开始使用Sequelize,不应该是findAndCountAll吗?也许方法名称从现在到两年前发生了变化。只是让看到这个的人知道。
【解决方案3】:

Sequelize documentation on count 链接到 a count method,它不允许您指定获取不同值计数的列:

Model.prototype.count = function(options) {
  options = Utils._.clone(options || {});
  conformOptions(options, this);
  Model.$injectScope(this.$scope, options);
  var col = '*';
  if (options.include) {
    col = this.name + '.' + this.primaryKeyField;
    expandIncludeAll.call(this, options);
    validateIncludedElements.call(this, options);
  }
  Utils.mapOptionFieldNames(options, this);
  options.plain = options.group ? false : true;
  options.dataType = new DataTypes.INTEGER();
  options.includeIgnoreAttributes = false;
  options.limit = null;
  options.offset = null;
  options.order = null;
  return this.aggregate(col, 'count', options);
};

如果您定义了主键,则基本上是 SELECT COUNT(DISTINCT(*))SELECT COUNT(DISTINCT(primaryKey))

要执行 SELECT category, COUNT(DISTINCT(product)) as 'countOfProducts' GROUP BY category 的 Sequelize 等效项,您可以:

model.findAll({
  attributes: [
    'category',
    [Sequelize.literal('COUNT(DISTINCT(product))'), 'countOfProducts']
  ],
  group: 'category'
})

【讨论】:

    【解决方案4】:

    我正在搜索 SELECT COUNT(0) 查询以获取续集,下面是答案。

        let existingUsers = await Users.count({
            where: whereClouser,
            attributes: [[sequelize.fn('COUNT', 0), 'count']]
        });
    

    【讨论】:

      【解决方案5】:

      关于您的问题,以便根据产品 id 获得产品的不同计数

      您只需将值为“id”的键“distinct”传递给您的计数对象,示例如下

      按照您的要求生成此 sql 查询

      SELECT COUNT(DISTINCT(`Product`.`id`)) as `count` 
      FROM `Product` 
      LEFT OUTER JOIN `Vendor` AS `vendor` ON `vendor`.`id` = `Product`.`vendorId` 
      WHERE (`vendor`.`isEnabled`=true );
      

      在 Sequelize 查询中添加 'distinct' 键

      Product.count({
              include: [{model: models.Vendor, as: 'vendor'}],
              where: [{ 'vendor.isEnabled' : true }],
              distinct: 'id' // since count is applied on Product model and distinct is directly passed to its object so Product.id will be selected
          });
      

      这种使用 'distinct' 键过滤掉不同计数或行的方式,我在 Sequelize 版本 6 中进行了测试。

      希望这会对您或其他人有所帮助!

      【讨论】:

        猜你喜欢
        • 2017-05-22
        • 1970-01-01
        • 1970-01-01
        • 2021-01-24
        • 2017-05-30
        • 2016-04-09
        • 2023-04-04
        • 2022-09-22
        相关资源
        最近更新 更多