在sequelize中,如何选择匹配多行不同值的记录?

问题描述 投票:0回答:3

作为示例,我有下表:

A | B
------
1 | 2
1 | 3
1 | 4
2 | 3
2 | 4
3 | 3

我想选择 B 中 A 列中值为 1 AND 2 的所有值。因此,在上面的示例中,我应该得到结果 (3,4),因为只有 3 和 4 的 A 列的值为 1 和 2。

我将如何在续集中做到这一点?

这是我尝试过的:

 db.myModel.findAll({
    where: {
      A: whatImSearching
    },
    attributes: ['A', 'B']
  })

whatImSearching = [1,2]

但是该解决方案返回的结果只有一个值匹配,即我将得到结果 (2,3,4)。但我应该只得到(3,4)。

javascript sql sequelize.js
3个回答
2
投票

注意:这是在 SQL 中完成的,就像评论中提到的 @daf 一样,类似的东西可以在 Sequelize 中实现。我把这个留作参考

您可以使用带有条件的分组,像这样

SELECT B 
FROM Table1 GROUP BY B
HAVING SUM(CASE WHEN A IN(1,2) THEN 1 ELSE 0 END) = 2

编辑

假设您有重复的值。这应该会更好

SELECT B 
FROM Table1 GROUP BY B
HAVING SUM(CASE WHEN A = 1 THEN 1 ELSE 0 END) = 1
    AND SUM(CASE WHEN A = 2 THEN 1 ELSE 0 END) = 1

2
投票

编辑:我没有立即看到纯粹的 Sequelize 方法来执行此操作,但是下面的内容应该可以达到您想要的位置,只需从数据库中带回一些额外的行即可。

假设您正在使用如下模型进行查询:

var model = sequelize.define('model', { 
    A: { type: Sequelize.TEXT }, 
    B: { type: Sequelize.TEXT }
}, {
    tableName: 'SomeTable',
    timestamps: false
})

你可以这样做:

var search = [1,2];
model.findAll({
    where: { A: { '$in': search } },
    attributes: ['A', 'B']
}).then(function(instances) {
  var unwrapped = instances.map(function(i) { 
    return i.get();
  });
  var withCounts = unwrapped.reduce(function(acc, cur) {
    var thisB = cur.B;
    var accItem = acc.filter(function(i) { 
      return i.B === thisB; 
    })[0];
    if (!accItem) {
      accItem = { B: thisB, count: 0 };
      acc.push(accItem);
    }
    accItem.count++;
  }, [])
  var hasAll = withCounts.filter(function(i) {
    return i.count === search.length;
  }).map(function(i) {
    return i.B;
  });
})

0
投票

正如 @daf 在他的回答中所说,你不能用纯粹的 Sequelize 来做到这一点,但是我们可以使用

literal
操作来包含一些 SQL,在数据库中计算更多,而用 Javascript 计算更少。

const { Sequelize } = require('sequelize');
const whatImSearching = [1, 2];

myModel.findAll({
  attributes: ['B'],
  where: {
    A: whatImSearching,
  },
  group: ['B'],
  having: Sequelize.literal(
    `count(distinct A) = ${whatImSearching.length}`
  ),
}).then(rows => rows.map(row => row.B)); // Objects to Values

.map()
之前,这将返回
[ { B: 3 }, { B: 4 } ]

此查询查找 A 列中具有列出的值的所有行,按 B 进行分组,然后将其限制为仅存在与搜索相同数量的条目的条目,确保我们只有具有所有所需值的条目.

查询执行(替换变量)以下内容:

SELECT B 
FROM myModel
WHERE A in (1, 2)
GROUP BY B
HAVING count(distinct a) = 2
© www.soinside.com 2019 - 2024. All rights reserved.