postgresql如何用连接表草拟不在语句中

时间:2017-01-25 17:08:50

标签: postgresql

我有3个postgresql表:文档,关键字和连接表。

我有查询,如果某些关键字与该文档相关,则会搜索document.id和document.date。这样做很好:

SELECT 
    documents.id, documents.document_date
FROM
    documents
        INNER JOIN
    documents_keywords ON documents_keywords.document_id = documents.id
        INNER JOIN
    keywords ON keywords.id = documents_keywords.keyword_id
WHERE
    keywords.keyword IN ('bread' , 'cake')
GROUP BY documents.id

返回:

 id | document_date 
----+-----------
  4 |      1200
 12 |      1280
(2 rows)

我还想排除关键字。我以为我可以这样做NOT IN

SELECT 
    documents.id, documents.document_date
FROM
    documents
        INNER JOIN
    documents_keywords ON documents_keywords.document_id = documents.id
        INNER JOIN
    keywords ON keywords.id = documents_keywords.keyword_id
WHERE
    keywords.keyword NOT IN ('cranberries')
GROUP BY documents.id

但是,无论我放置什么关键字,它总是返回空白:

 id | document_date 
----+-----------
(0 rows)

这是不正确的。我期待:

 id | document_date 
----+-----------
  4 |      1200
(1 row)

1 个答案:

答案 0 :(得分:0)

您可能想要使用数组表达式,如下所示:

 WHERE keyword = any(array['bread', 'cake'])

当你想要包含一行时。

如果要排除某些内容,则必须在反向条件的子选择中执行NOT IN,例如

SELECT ... WHERE document_id NOT IN
(SELECT document_id FROM ...joins... WHERE keyword = ANY(array['cranberry']))

这是我放在一起的一个例子:

WITH documents(d_id, date) AS (
VALUES(1,'1000'),(2,'2000'),(3,'3000'),(4,'4000')
),

keywords(k_id, keyword) AS (
VALUES(1, 'cake'), (2, 'bread'), (3, 'cranberry')
),
documents_keywords (d_id, k_id) AS (
VALUES(1,1),(1,2),(2,2),(2,3),(3,3)
)
SELECT * FROM documents where d_id NOT IN (
  SELECT d_id FROM 
  documents 
  JOIN documents_keywords USING(d_id) 
  JOIN keywords USING(k_id)
  WHERE keyword = ANY(array['cranberry'])
)

此外,我不确定您使用GROUP BY的原因,我认为您不需要它。