作为示例,我有下表:
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)。
注意:这是在 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
编辑:我没有立即看到纯粹的 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;
});
})
正如 @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