自联接和内部联接以删除重复项

时间:2017-01-24 14:05:43

标签: sql oracle

我对此感到困惑,而且我对SQL相对较新。

以下是我们提出的问题:

  

列出我们拥有的所有产品的productname和vendorid   从多个供应商那里购买(提示:你需要一个自我加入和   另外一个INNER JOIN要解决,不要忘记删除任何内容   重复!!)

以下是我们正在使用的表格的屏幕截图:

enter image description here

这是我的......我知道这是错的。它在某种程度上起作用,而不是教授如何想要它。

SELECT DISTINCT productname, product_vendors.vendorid 
FROM products INNER JOIN Product_Vendors
ON products.PRODUCTNUMBER = PRODUCT_VENDORS.PRODUCTNUMBER
INNER JOIN vendors ON Product_Vendors.VENDORID = vendors.VENDORID
ORDER BY products.PRODUCTNAME;

预期输出提供了教授:

enter image description here

3 个答案:

答案 0 :(得分:3)

我同意@jarlh的观点,即附加信息会有所帮助 - 即数据中是否有重复数据或只是重复数据等。

那说,这应该是你的开始

SELECT
    c.productname   AS 'Product'
    ,a.vendorid     AS 'Vendor1'
    ,b.vendorid     AS 'Vendor2'

FROM
    product_vendors AS a
JOIN 
    product_vendors AS b
        ON 
        a.productnumber = b.productnumber
        AND a.vendorid <> b.vendorid
JOIN
    dbo.products AS c
        ON
        a.productnumber = c.productnumber

这将限制“产品供应商”的数量仅限于具有不匹配供应商的产品。 从那里,您将加入产品以撤回产品名称。

此外 - 编写格式,清洁代码使梦想成真:)

答案 1 :(得分:1)

此问题的解决方案通常是使用COUNT OVER计算每个产品的供应商,并且只使用多个产品。简单地:

select productname, vendorid
from
(
  select 
    p.productname, 
    pv.vendorid, 
    count(*) over (partition by product) as cnt
  from products p
  join product_vendors pv using (productnumber)
)
where cnt > 1;

如果没有窗口函数,那么一个选项就是聚合product_vendors并使用这个结果:

select p.productname, pv.vendorid
from
(
  select productid 
  from product_vendors
  group by productname
  having count(*) > 1
) px
join products p using (productid)
join product_vendors pv using (productid);

或检查是否存在该产品的其他供应商:

select 
  p.productname, 
  pv.vendorid, 
  count(*) over (partition by product) as cnt
from products p
join product_vendors pv on pv.productnumber = p.productnumber
where exists
(
  select *
  from product_vendors other
  where other.productnumber = pv.productnumber
  and other.vendorid <> pv.vendorid
);

在这两种方法中,我都认为需要消除重复,因为products中每个产品应该有一行,product_vendors中每个产品和供应商应该有一行。所以我想你的教授在想的是:

select distinct
  p.productname, 
  pv.vendorid
from products p
join product_vendors pv on pv.productnumber = p.productnumber
join product_vendors other on other.productnumber = pv.productnumber
                           and other.vendorid <> pv.vendorid

然而,这是我不推荐的方法。您将产品的所有供应商组合在一起(例如,对于一种产品,您只有10种供应商,如果我没有弄错的话,您只有45种产品组合)。所以你创建一个大的中间结果只是为了稍后用DISTINCT来解散大部分结果。不要那样做。请记住:SELECT DISTINCT通常是一个写得不好的查询的指标(即不必要的连接导致你实际上并不感兴趣的太多组合)。

答案 2 :(得分:0)

SELECT DISTINCT p.name AS product, v.id
FROM products p 
     INNER JOIN product_vendors pv ON p.id = pv.productid
     INNER JOIN product_vendors pv2 ON pv.productid = pv2.productid AND pv.vendorid != pv2.vendorid 
     INNER JOIN vendors v ON v.id = pv.vendorid
ORDER BY p.name