我有一个看起来像这样的表(简化):
CREATE TABLE IF NOT EXISTS records (
user_id uuid NOT NULL
ts timestamptz NOT NULL,
op_type text NOT NULL,
PRIMARY KEY (user_id, ts, op_type)
);
我不能为实际目的改变PRIMARY KEY。
我正在尝试编写一个查询,以获取给定records
的所有user_id
,对于特定记录,ts
和op_type
不会匹配一系列排除。
我不完全确定正确的postgres术语,所以让我看看这个例子是否使我的约束更清晰:
这个数组看起来像这样(在JavaScript中):
var excludes = [
[DATE1, 'OP1'],
[DATE2, 'OP2']
]
如果对于给定的用户ID,数据库中有如下所示的行:
ts | op_type
----------------------------+-------------
DATE1 | OP1
DATE2 | OP2
DATE1 | OP3
DATE2 | OP1
OTHER DATE | OP1
OTHER DATE | OP2
然后,使用上面的excludes
,我想运行一个返回EXCEPT或前两行的查询,因为它们完全匹配。
我的尝试是这样做:
client.query(`
SELECT * FROM records
WHERE
user_id = $1
AND (ts, op_type) NOT IN ($2)
`, [userId, excluding])
但我得到“匿名复合类型的输入未实现”。我不确定如何正确输入excluding
或者这是否是正确的方法。
答案 0 :(得分:3)
查询可能如下所示
SELECT *
FROM records
WHERE user_id = 'a0eebc999c0b4ef8bb6d6bb9bd380a11'
AND (ts, op_type) NOT IN (('2016-01-01', 'OP1'), ('2016-01-02', 'OP2'));
因此,如果您想将条件作为单个参数传递,那么excluding
应该是格式为的字符串:
('2016-01-01', 'OP1'), ('2016-01-02', 'OP2')
似乎没有简单的方法将条件字符串作为参数传递给query()
。您可以尝试编写一个函数来以正确的格式获取字符串(我不是JS开发人员,但这段代码似乎运行良好):
excluding = function(exc) {
var s = '(';
for (var i = 0; i < exc.length; i++)
s = s+ '(\''+ exc[i][0]+ '\',\''+ exc[i][1]+ '\'),';
return s.slice(0, -1)+ ')';
};
var excludes = [
['2016-01-01', 'OP1'],
['2016-01-02', 'OP2']
];
// ...
client.query(
'SELECT * FROM records '+
'WHERE user_id = $1 '+
'AND (ts, op_type) NOT IN ' + excluding(excludes),
[userId])