【问题标题】:Selecting rows that has exactly same data as other table选择与其他表具有完全相同数据的行
【发布时间】:2013-07-03 10:18:40
【问题描述】:

我有这些表: 产品文章产品_文章

比方说,product_ids 是:p1p2 article_ids 是:a1a2 a3 product_articles 是:

  • (p1,a1)
  • (p1,a2)
  • (p2,a1)
  • (p2,a1)
  • (p2,a2)
  • (p2,a3)

如何查询product_id,它只有a1,a2,不多也不少?

【问题讨论】:

  • Oracle 数据库 PL/SQL

标签: oracle join plsql


【解决方案1】:

更新试试

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 两个查询的演示

【讨论】:

  • 我认为“一点也不差”的意思是产品必须同时具有a1a2(当然可能是错误的);这个will find products with eitherCounting the distinct articles 会“解决”这个问题,可能有更好的方法......
  • HAVING COUNT(*)=(SELECT COUNT(article_id) FROM article WHERE article_id in (1,2)) 应该没问题吧?
  • @AlexPoole 在 OP 的情况下 (product_id, article_id) 是一个 PK,因此是 UNIQE。因此不能有重复。所以恕我直言,查询完全按照要求进行。
  • 没什么,我喜欢,但是在教员我们没有学过 CASE,所以他们不允许
  • @JovanMeshkov 查看另一种连接方法的更新答案
【解决方案2】:

这是“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”的地方。或者你有四篇文章中的三篇,等等。

【讨论】:

    【解决方案3】:

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

    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 没有加入任何行)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-07
      • 2014-06-08
      • 2020-10-03
      • 2022-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多