web-dev-qa-db-fra.com

Comment obtenir un décompte distinct avec séquelle?

J'essaie d'obtenir un décompte distinct d'une colonne particulière en utilisant Sequelize. Ma première tentative utilise la méthode "count" de mon modèle, mais cela ne semble pas possible.

La fonction DISTINCT est nécessaire car je joins d'autres tables et filtre les lignes du parent en fonction des tables associées.

voici la requête que j'aimerais:

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

en utilisant la requête suivante sur mon modèle de produit:

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

Génère la requête suivante:

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

Il semble que cela soit désormais pris en charge dans les versions 1.7.0+ de Sequelize.

les méthodes count et findAndCountAll d'un modèle vous donneront un compte "réel" ou "distinct" de votre modèle parent.

5
Adam

MISE À JOUR: Nouvelle version

Comme mentionné dans les commentaires, les choses ont changé depuis mon post d'origine. Il existe désormais des options distinct et col distinctes. Les documents pour distinct indiquent:

Appliquer COUNT (DISTINCT (col)) sur la clé primaire ou sur options.col.

Il semble que vous vouliez maintenant quelque chose comme:

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

Message d'origine

Après avoir regardé méthode Model.count dans lib/model.js et tracé du code, j'ai constaté que lorsque vous utilisez Model.count, Vous pouvez simplement ajouter tout type d'arguments de fonction d'agrégation pris en charge par MYSQL à votre objet d'options. Le code suivant vous donnera le nombre de valeurs différentes dans MyModel's someColumn:

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

Ce code génère efficacement une requête de ce type: SELECT COUNT(args) FROM MyModel WHERE ..., où args sont toutes les propriétés de l'objet options qui ne sont pas réservées (telles que DISTINCT, LIMIT etc).

22
Domi

la documentation Sequelize sur count renvoie à ne méthode de comptage qui ne vous permet pas de spécifier la colonne pour obtenir le nombre de valeurs distinctes:

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);
};

Fondamentalement SELECT COUNT(DISTINCT(*)) ou SELECT COUNT(DISTINCT(primaryKey)) si vous avez défini une clé primaire.

Pour faire l'équivalent Sequelize de SELECT category, COUNT(DISTINCT(product)) as 'countOfProducts' GROUP BY category, vous feriez:

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