【问题标题】:SQL join - duplicate rowsSQL 连接 - 重复行
【发布时间】:2015-07-17 13:41:42
【问题描述】:

我有三个表(简化版 - 整个画面有点复杂)。

TABLE: CUSTOMER    TABLE: PURCHASE1           TABLE: PURCHASE2
===============    =======================    =======================
CustomerID         CustomerID  | ProductID    CustomerID  | ProductID
---------------    ------------|----------    ------------|----------
1                  1           | 51            1          | 81
2                  1           | 52            1          | 82
3                  2           | 52            1          | 83

我知道表格结构不是最好的,但这不是我需要帮助的地方。如果这有助于提供上下文,购买表中的产品属于不同类型。

我正在尝试加入表格,使用如下查询:

Select 
    customer.customerid, purchase1.productid as P1, 
    purchase2.productid as P2
From  
    customer
Left join 
    purchase1 on customer.customerid = purchase1.customerid
Left join 
    purchase2 on customer.customerid = purchase2.customerid
Where 
    customer.customerid = 1;

这会产生以下内容:

CustomerID | P1 | P2
--------------------
1          | 51 | 81
1          | 51 | 82
1          | 51 | 83
1          | 52 | 81
1          | 52 | 82
1          | 52 | 83

我怎样才能让它这样做呢?

CustomerID | P1   | P2
-----------|------|---
1          | 51   | null
1          | 52   | null
1          | null | 81
1          | null | 82
1          | null | 83

第一个表对于 P1 和 P2 的每个组合都有一行。第二个表只有一行用于每个客户-产品组合。

我可以在不使用 UNION 的情况下执行此操作吗?我问的原因是因为查询将变得更加复杂,使用不在 PURCHASE1 或 PURCHASE2 中的其他行的列。

如果我必须使用 UNION,我该怎么做才能让我仍然可以从其他表中进行选择并在我的查询中包含其他列?

【问题讨论】:

    标签: sql oracle tsql oracle11g oracle10g


    【解决方案1】:

    使用联合。 See DEMO。在联合中,您必须在两个查询中具有相同数量的列,因此使用 NULL 来匹配两个查询中的列数

    Select * from (Select customer.customerid, purchase1.productid as P1, NULL as P2
    from customer
    INNER join purchase1
    on customer.customerid = purchase1.customerid
    
    UNION ALL
    
    Select customer.customerid, NULL as P1, purchase2.productid as P2
    from customer 
    INNER join purchase2
    on customer.customerid = purchase2.customerid) tb
    where tb.customerid = 1;
    

    【讨论】:

    • 谢谢,但是如果我有第三张桌子呢?这个与客户是一对一的关系,我希望它出现在查询的每一行上吗?有没有办法在不将逻辑放入两个 select 语句的情况下做到这一点?
    • 最好将您的实际问题包含在样本数据和预期输出中。现在,你有什么问题,有答案,更多更新你的问题
    【解决方案2】:

    我会这样做:

    select customerid, p1, p2
      from customer
      left join (
        select customerid, productid p1, null p2 from purchase1
        union all
        select customerid, null p1, productid p2 from purchase2
        ) using (customerid)
      where customerid = 1;
    

    SQLFiddle demo

    现在您可以附加其他表格而无需重复逻辑。

    【讨论】:

      【解决方案3】:

      我首先将所有表联合起来,然后将它们加入到客户表中——就像这样:

      with customer as (select 1 customerid, 'bob' name from dual union all
                        select 2 customerid, 'ted' name from dual union all
                        select 3 customerid, 'joe' name from dual),
          purchase1 as (select 1 customerid, 51 productid from dual union all
                        select 1 customerid, 52 productid from dual union all
                        select 2 customerid, 52 productid from dual),
          purchase2 as (select 1 customerid, 81 productid from dual union all
                        select 1 customerid, 82 productid from dual union all
                        select 1 customerid, 83 productid from dual),
          -- end of mimicking your table and data; main query is below:
          purchases as (select customerid, productid productid1, null productid2
                        from   purchase1
                        union all
                        select customerid, null productid1, productid productid2
                        from   purchase2)
      select c.customerid,
             c.name,
             p.productid1,
             p.productid2
      from   customer c
             inner join purchases p on (c.customerid = p.customerid)
      order by c.customerid,
               p.productid1,
               p.productid2;
      
      CUSTOMERID NAME PRODUCTID1 PRODUCTID2
      ---------- ---- ---------- ----------
               1 bob          51           
               1 bob          52           
               1 bob                     81
               1 bob                     82
               1 bob                     83
               2 ted          52           
      

      【讨论】:

        【解决方案4】:

        将其更改为像这样的联合查询可能是最简单的。

        select customer.customerid, purchase1.productid as P1, null as P2
        from customer
        left join purchase1
        on customer.customerid = purchase1.customerid
        union all
        select customer.customerid, null as P1, purchase2.productid as P2
        from customer
        left join purchase2
        on customer.customerid = purchase2.customerid
        where customer.customerid = 1;
        

        【讨论】:

          【解决方案5】:

          这在子查询中使用联合,但方式略有不同,这可能会为您提供更大的灵活性。

          select distinct t1.pID,t2.pID
          from (select ID,pID from Puchase1
                  union all
                  select ID, null from Purchase1) t1
          right join (select ID,pID from Purchase2
                      union all
                      select ID, null from Purchase2) t2
          on t1.ID = t2.ID
          where t1.ID = 1
          and (t1.pID is not null or t2.pID is not null)
          and (t1.pID is null or t2.pID is null)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-08-02
            • 1970-01-01
            • 1970-01-01
            • 2011-10-23
            • 2014-04-08
            • 2013-04-22
            • 2013-07-22
            • 1970-01-01
            相关资源
            最近更新 更多