0

我目前正在节点中使用 postgres 来查询所有具有与其帐户关联的特定标签的用户(注意:我正在使用node-postgres):

query = 'SELECT tags.*, pl.email FROM admin.tags tags
LEFT JOIN gameday.player_settings pl
ON tags.player_id = pl.id
WHERE tags.tag = $1'

client.query(
  query,
  [tagName],
  function(err, results) {
    ...

[tagName]然后传递到WHERE子句中。

我的目标是通过未知数量的标签进行查询,并返回所有拥有与其帐户相关联的所有标签的用户。因此,[tagName]我不想传入一个未知长度的数组[tagNames],但是我不知道如何实现这一点。

4

1 回答 1

2

你需要把问题倒过来。代替:

哪些用户拥有所有这些标签,您需要询问哪些用户没有这些标签中的一个或多个。这是一个双重否定。

您还需要一种传递标签集的方法。如果客户端语言绑定支持,最好的方法是作为数组值查询参数。如果客户端绑定不支持数组值参数,您将需要动态 SQL。

一种公式可能是(未经测试,因为您没有提供示例模式和数据):

SELECT pl.email
FROM gameday.player_settings pl
WHERE NOT EXISTS (
  SELECT 1
  FROM unnest(?) AS wanted_tags(tag)
  LEFT JOIN admin.tags tags
    ON tags.tag = wanted_tags.tag
  WHERE  tags.player_id = pl.id
    AND wanted_tags.tag IS NULL
);

进行左连接和过滤IS NULL称为左反连接。它保留左连接条件不匹配的wanted_tags因此,在这种情况下,仅当没有与此 player 关联的匹配标签时,我们才保留数组中的标签。如果留下任何标签,则WHERE NOT EXISTS返回 false,因此玩家被排除在外。

三思而后行不是吗?这样测试很容易出错。

这里?应该是你的编程语言 PostgreSQL 数据库绑定的查询参数占位符。我不知道 node.js 是什么。仅当您可以在节点中将数组作为查询参数传递时,这才有效。如果没有,您将不得不使用动态 SQL 来生成ARRAY['x','y','z']表达式或(VALUES ('x'), ('y'), ('z'))子查询。

PS 如果可能,请提供示例架构和带有问题的数据。http://sqlfiddle.com/很方便。

于 2015-08-19T11:49:36.030 回答