选择与其他表具有完全相同数据的行

时间:2013-07-03 10:18:41

标签: oracle join plsql

我有这些表格: 产品文章 Product_Articles enter image description here

enter image description here

enter image description here

可以说,product_ids是: p1 p2 article_ids是: a1 a2 A3 product_articles是:

  • (P1,A1)
  • (P1,A2)
  • (P2,A1)
  • (P2,A1)
  • (P2,A2)
  • (P2,a3)的

如何查询product_id,它只有a1,a2,没有更少,仅此而已?

3 个答案:

答案 0 :(得分:2)

更新尝试

SELECT p.* 
  FROM products p JOIN 
(
  SELECT product_id
    FROM product_articles
   GROUP BY product_id
  HAVING COUNT(*) = SUM(CASE WHEN article_id IN (1, 2) THEN 1 ELSE 0 END)
     AND SUM(CASE WHEN article_id IN (1, 2) THEN 1 ELSE 0 END) = 2
) q ON p.product_id = q.product_id

SELECT p.* 
  FROM products p JOIN 
(
  SELECT product_id, COUNT(*) a_count
    FROM product_articles
   WHERE article_id IN (1, 2)
   GROUP BY product_id
  HAVING COUNT(*) = 2
) a ON p.product_id = a.product_id JOIN
(
  SELECT product_id, COUNT(*) total_count
    FROM product_articles
   GROUP BY product_id
) b ON p.product_id = b.product_id
WHERE a.a_count = b.total_count

以下是两个查询的 SQLFiddle 演示

答案 1 :(得分:1)

这是“set-within-sets”子查询的示例。我主张使用带有having子句的聚合来表示逻辑,因为这是表达关系的最常用方法。

我们的想法是,您可以使用类似于使用where语句的方式计算产品中文章的外观(在本例中)。代码有点复杂,但它提供了灵活性。在您的情况下,这将是:

select pa.product_id
from product_articles pa
group by pa.product_id
having sum(case when pa.article_id = 'a1' then 1 else 0 end) > 0 and
       sum(case when pa.article_id = 'a2' then 1 else 0 end) > 0 and
       sum(case when pa.article_id not in ('a1', 'a2') then 1 else 0 end) = 0;

前两个条款计算两篇文章的外观,确保每篇文章至少出现一次。最后一个计算没有这两篇文章的行数,确保没有。

您可以看到这很容易概括为更多文章。或查询“a1”和“a2”但不是“a3”的查询。或者您有四个特定文章中的三个,依此类推。

答案 2 :(得分:0)

我相信这可以完全使用关系连接完成,如下所示:

SELECT DISTINCT pa1.PRODUCT_ID
  FROM PRODUCT_ARTICLES pa1
  INNER JOIN PRODUCT_ARTICLES pa2
    ON (pa2.PRODUCT_ID = pa1.PRODUCT_ID)
  LEFT OUTER JOIN (SELECT *
                     FROM PRODUCT_ARTICLES
                     WHERE ARTICLE_ID NOT IN (1, 2)) pa3
    ON (pa3.PRODUCT_ID = pa1.PRODUCT_ID)
  WHERE pa1.ARTICLE_ID = 1 AND
        pa2.ARTICLE_ID = 2 AND
        pa3.PRODUCT_ID IS NULL

SQLFiddle here

内部联接查找与我们关注的文章相关的产品(第1条和第2条 - 生产产品1和2)。左外部查找与我们不关心的文章相关的产品(任何文章 1和2之外),然后只接受没有任何不需要的文章的产品(即pa3.PRODUCT_ID IS NULL ,表示没有加入pa3的行。)