我有一个两个表,一个用于映射到类别的文档。
Documents
id | document_name
1 | somename.doc
2 | anothername.doc
Documents_to_categories
cat_id | doc_id
10 | 1
10 | 2
11 | 3
12 | 1
某些文档可以映射到多个类别。我想要的是能够选择属于多个类别的文档,如过滤方案。
基本上在脚本中我有一个文档ID数组,它是搜索结果。我需要根据类别过滤掉这些文档。
这就像我的目标一样(我知道它不起作用,但是例如)。
SELECT *
FROM Documents_to_categories A
JOIN Documents B ON A.doc_id = B.id
WHERE B.id IN (6703,6614,2286)
AND A.cat_id = :ID0
AND A.cat_id = :ID1
编辑:对不起,我第一次发帖回复的所有人都不清楚问题。希望这更清楚我想要的东西。
答案 0 :(得分:3)
select a.doc_id, count(*)
from Documents_to_categories A
where a.doc_id in (<doc_id list>)
and a.cat_id in (<cat_id list>)
group by doc_id
having count(*) = <cat_id list length>
将返回一个doc_ids列表,其中包含cat_id list
中每个类别的条目。请注意,您还需要提供having
子句列表的长度。
您可以使用此选项检索外部选择中所需的所有详细信息,使用上面的选择来填充doc_ids的inlist。
这最终看起来像:
select b.id, b.document_name, a,cat_id
from Documents_to_categories A,
Documents B
where a.doc_id = b.id
and b.id in (select mylist.doc_id from (
select a.doc_id, count(*)
from Documents_to_categories A
where a.doc_id in (<doc_id list>)
and a.cat_id in (<cat_id list>)
group by doc_id
having count(*) = <cat_id list length>
) as mylist )
答案 1 :(得分:1)
假设您将文档ID列表作为逗号分隔列表传递,最简单的解决方案是使用动态SQL:
L_CURSOR SYS_REFCURSOR;
L_QUERY VARCHAR2(5000) DEFAULT 'SELECT d.document_name
FROM DOCUMENTS d
JOIN DOCUMENTS_TO_CATEGORIES c10 ON c10.doc_id = d.id
AND c10.cat_id = 10
JOIN DOCUMENTS_TO_CATEGORIES c12 ON c12.doc_id = d.id
AND c12.cat_id = 12
WHERE d.id IN (:document_list)'
BEGIN
FOR I IN 0 .. (TRUNC(LENGTH(L_QUERY) / 255)) LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(L_QUERY, I * 255 + 1, 255));
END LOOP;
OPEN L_CURSOR FOR L_QUERY USING IN_DOCUMENT_LIST;
RETURN L_CURSOR;
END;
我想要的是能够选择属于多个类别的文档,例如过滤方案。例如:我想按类别10和12进行筛选,因此只有属于10和12的文档才会返回(在本例中为doc 1)。
SELECT d.document_name
FROM DOCUMENTS d
JOIN DOCUMENTS_TO_CATEGORIES dtc ON dtc.doc_id = d.id
WHERE dtc.cat_id IN (10, 12)
GROUP BY d.document_name
HAVING COUNT(DISTINCT dtc.cat_id) = 2
SELECT d.document_name
FROM DOCUMENTS d
JOIN DOCUMENTS_TO_CATEGORIES c10 ON c10.doc_id = d.id
AND c10.cat_id = 10
JOIN DOCUMENTS_TO_CATEGORIES c12 ON c12.doc_id = d.id
AND c12.cat_id = 12
答案 2 :(得分:0)
要获取仅出现在BOTH类别中的文档,可以使用ANSI SQL INTERSECT运算符,如下所示:
SELECT Documents.document_name
FROM Documents
WHERE Documents.id IN
(
SELECT Documents_to_categories.docid
FROM Documents_to_categories
WHERE Documents_to_categories.catid = 10
INTERSECT
SELECT Documents_to_categories.docid
FROM Documents_to_categories
WHERE Documents_to_categories.catid = 12
/*.. add additional filters */
)
答案 3 :(得分:0)
我想按类别10过滤 12,所以只有文件属于10 12返回(在本例中为doc 1)
您需要从您的应用生成SQL查询:
SELECT
d.id,
d.document_name
FROM
Documents as d,
Documents_to_categories dc1,
Documents_to_categories dc2,
WHERE
d.id = dc1.doc_id
AND d.id = dc2.doc_id
AND dc2.cat_id = 10
AND dc1.cat_id = 12
这适用于所有主要数据库服务器。
而不是从文件中选择 表,我想从中选择它 文档ID的数组。
不确定你的意思。关系世界中没有 array 实体(例如SQL)。有一个被称为表或可能设置。
答案 4 :(得分:0)
这为您提供属于至少一个类别的所有文档,其中至少有一个类别为10或12。
SELECT
doc_id
FROM Documents_to_categories
WHERE doc_id IN (<your list of doc_ids>)
GROUP BY doc_id
HAVING COUNT(*) > 1
AND MAX(CASE WHEN cat_id IN (10, 12) THEN 1 ELSE 0 END) = 1;