过滤可能有多个类别的数据

Asl*_*986 5 postgresql

我有一张如下表:

Annotation (
    document,
    term,
    category
)
Run Code Online (Sandbox Code Playgroud)

其中documentterm是一些ID,category而是一个整数。

这对夫妇document-term不是唯一的,即我可以拥有不同类别的同一对夫妇。

document_id_1, term_id_1, category_1
document_id_1, term_id_1, category_2
document_id_1, term_id_1, category_3
Run Code Online (Sandbox Code Playgroud)

我想设计一个查询,使其仅返回一对夫妇document-term对于他们来说,只有一行category = 1.

例如,在前面的例子中,没有返回这对夫妇document_id_1-term_id_1因为还存在其他两行,具有不同的 值category

你能给我一些关于如何做到这一点的提示吗?

dez*_*zso 8

如果我理解正确,实现此目的的一种方法是获取那些行 where category = 1,然后检查非类别 1 行是否不存在:

SELECT document, term
FROM Annotation ann
WHERE 
    category = 1
    AND NOT EXISTS (
        SELECT 1
        FROM Annotation a
        WHERE 
            a.document = ann.document
            AND a.term = ann.term
            AND category <> 1
    )
;
Run Code Online (Sandbox Code Playgroud)

(感谢 DavideChicco.it 表明这过于复杂)。


Tar*_*ryn 7

你应该能够使用类似的东西:

select a1.document, a1.term, a1.category
from annotation a1
where category = 1
  and exists (select document, term
              from annotation a2
              where a1.document = a2.document
                and a1.term = a2.term
              group by document, term
              having count(distinct category) = 1)
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo

这对于行,其中将过滤category =1但随后进行检查,以确保documentterm仅在表中有一个明显的一行。


And*_*y M 7

如果这是 PostgreSQL 8.4+,您还可以尝试以下操作:

WITH counted AS (
  SELECT
    *,
    COUNT(*) OVER (PARTITION BY document, term) AS category_count
  FROM Annotation
)
SELECT
  document,
  term,
  category
FROM counted
WHERE category = 1
  AND category_count = 1
;
Run Code Online (Sandbox Code Playgroud)

counted公共表表达式返回行以每每个分区的行数提供(document, term)。主查询只需要以某行属于特定类别且对应的行数为1为条件进行过滤。

另请注意,如果您的设计允许 的重复条目(document, term, category),则需要替换COUNT(*)COUNT(DISTINCT category)。(因此,这可能会导致(document, term)输出中的每一行多于一行。)