在Postgres中查询未知数量的关键字

时间:2015-08-19 11:24:10

标签: sql node.js postgresql relational-division node-postgres

我目前在节点中使用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],而是我不知道如何实现这一目标。

1 个答案:

答案 0 :(得分: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数组中的标记。如果剩下任何标记,WHERE NOT EXISTS将返回false,因此排除了播放器。

双重思考,不是吗?这样 test 很容易犯错误。

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

P.S。如果可能,请提供示例架构和数据http://sqlfiddle.com/很方便。