我正在使用Knex,一个非常好的SQL构建器。
我有一个名为Foo
的表,其中有3列
+--------------+-----------------+
| id | PK |
+--------------+-----------------+
| idFoo | FK (not unique) |
+--------------+-----------------+
| serialNumber | Number |
+--------------+-----------------+
我想选择idFoo IN (1, 2, 3)
的所有行。
但是我想避免基于相同idFoo
的重复记录。
由于该列不是唯一的,因此可能有许多行具有相同的idFoo
。
我上面的查询当然会以idFoo IN (1, 2, 3)
返回所有内容,甚至是重复内容。
db.select(
"id",
"idFoo",
"age"
)
.from("foo")
.whereIn("idFoo", [1, 2, 3])
然而,这将返回重复idFoo
的结果,如下所示:
+----+-------+--------------+
| id | idFoo | serialNumber |
+----+-------+--------------+
| 1 | 2 | 56454 |
+----+-------+--------------+
| 2 | 3 | 75757 |
+----+-------+--------------+
| 3 | 3 | 00909 |
+----+-------+--------------+
| 4 | 1 | 64421 |
+----+-------+--------------+
我需要的是:
+----+-------+--------------+
| id | idFoo | serialNumber |
+----+-------+--------------+
| 1 | 2 | 56454 |
+----+-------+--------------+
| 3 | 3 | 00909 |
+----+-------+--------------+
| 4 | 1 | 64421 |
+----+-------+--------------+
我可以获取结果并使用Javascript过滤掉重复项。我特别想避免这种情况,并将其写入Knex。
问题是如何使用Knex代码执行此操作?
我知道可以使用普通的SQL(可能使用GROUP BY
)来完成它,但我特别想在不使用原始SQL的情况下在“纯”knex中实现这一点。
答案 0 :(得分:1)
在普通的sql中,你这样做。
您执行self join
并尝试查找具有相同idFoo
但更大id
的行,如果您没有找到NULL
。而且会知道你是更大的一个。
SELECT t1.id, t1.idFoo, t1.serialNumber
FROM foo as t1
LEFT JOIN foo as t2
ON t1.id < t2.id
AND t1.idFoo = t2.idFoo
WHERE t2.idFoo IS NULL
请检查knex.js上的left join
修改强>
只需检查文档构建(未测试):
knex.select('t1.*')
.from('foo as t1')
.leftJoin('foo as t2', function() {
this.on('t1.id', '<', 't2.id')
.andOn('t1.idFoo ', '=', 't2.idFoo')
})
.whereNull("t2.idFoo")
答案 1 :(得分:1)
Knex.js本身支持groupBy。你可以写:
knex('foo').whereIn('id',
knex('foo').max('id').groupBy('idFoo')
)
将其重写为以下SQL:
SELECT * FROM foo
WHERE id IN (
SELECT max(id) FROM foo
GROUP BY idFoo
)
请注意,您需要使用子选择来确保您不会混合同一组中不同行的值。