【问题标题】:Oracle SQL union table1 with table2 with null result if table2 contains more如果 table2 包含更多,则 Oracle SQL 将 table1 与 table2 联合,结果为空
【发布时间】:2020-10-30 02:55:08
【问题描述】:

我会尝试用一个例子来解释。

我有 2 张桌子:

table1
column1 column2 column3
000001   ABC     COD1
000001   ABC     COD2
000002   BCD     COD3
000003   EDF     COD1
000003   EDF     COD3
000004   FGH     COD1
000004   FGH     COD2
000004   FGH     COD3
000004   FGH     COD4

table2
column3
COD1
COD2
COD3
COD4
COD5
COD6
COD7

table2 仅包含 table1 的 column3 的所有可能代码(仅此而已)。 table1 包含我的真实数据。 我不要 table2 COD5 COD6 和 COD7

我必须得到这样的结果

000001   ABC     COD1
000001   ABC     COD2
null     null    COD3
null     null    COD4
null     null    COD1
null     null    COD2
000002   BCD     COD3
null     null    COD4
000003   EDF     COD1
null     null    COD2
000003   EDF     COD3
null     null    COD4
000004   FGH     COD1
000004   FGH     COD2
000004   FGH     COD3
000004   FGH     COD4

我需要使用 oracle SQL 来执行此操作,但我不确定是否可行。如有必要,我可以接受第一列始终是我当前的 column1(即使 column2 为空)。我不想重复,例如两个 000004 FGH COD4 但如果为空,我想重复。

我尝试了我所知道的一切......但我能做的最好的事情是在我需要指定 column1 条件的子查询上使用减号或右连接进行联合。

编辑这是一个朋友在我尝试时找到的正确答案

select * from
(select distinct a.col1, a.col2
from table1 a
right join (select col3 from table2 f
 where f.col3 IN ('COD1','COD3','COD6')) b
on a.col3 = b.col3),
(select col3 from table2 f
 where f.col3 IN ('COD1','COD3','COD6'));

【问题讨论】:

    标签: sql oracle join left-join union


    【解决方案1】:

    您可以使用cross join 生成行,然后使用left join

    select t1.col1, t1.col2, c3.col3
    from (select distinct col1 from table1) c1 cross join
         table2 c3 left join
         table1 t1
         on t1.col1 = c1.col1 and t1.col3 = c3.col3
    order by c1.col1, c3.col3;
    

    注意:前两列中有NULL 值似乎很奇怪。这会导致行完全重复。如果您使用select c1.col1, t1.col2, c3.col3,您将在第一列中有有效值。

    【讨论】:

    • 好吧,我忘记了两件事。 1.我不想重复。 2.我要第二张表CODX的几张
    • 我知道这很奇怪,但如果可能的话,我需要这样的东西。基本上我需要一遍又一遍地重复第二个表的一些值,并且只有在该表使用该代码得到任何结果时才显示表一的结果。
    【解决方案2】:

    您需要使用cross joinleft join如下:

    SQL> with table1 (col1,col2,col3) as
      2  (select '000001','ABC','COD1' from dual union all
      3  select '000001','ABC','COD2' from dual union all
      4  select '000002','BCD','COD3' from dual union all
      5  select '000003','EDF','COD1' from dual union all
      6  select '000003','EDF','COD3' from dual ),
      7  TABLE2 (COL3) AS
      8  (SELECT 'COD1' FROM DUAL UNION ALL
      9  SELECT 'COD2' FROM DUAL UNION ALL
     10  SELECT 'COD3' FROM DUAL UNION ALL
     11  SELECT 'COD4' FROM DUAL UNION ALL
     12  SELECT 'COD5' FROM DUAL)
     13  select t11.col1, T11.COL2, T2.COL3
     14  from (SELECT DISTINCT COL1 FROM TABLE1) T1
     15  CROSS JOIN (SELECT * FROM TABLE2 WHERE COL3 IN (SELECT COL3 FROM TABLE1)) T2
     16  LEFT JOIN TABLE1 T11 ON T11.COL1 = T1.COL1 AND T2.COL3 = T11.COL3
     17  ORDER BY T1.COL1, T2.COL3;
    
    COL1   COL COL3
    ------ --- ----
    000001 ABC COD1
    000001 ABC COD2
               COD3
               COD1
               COD2
    000002 BCD COD3
    000003 EDF COD1
               COD2
    000003 EDF COD3
    
    9 rows selected.
    
    SQL>
    

    【讨论】:

    • 我编辑了我的问题,因为我忘记了一些我需要的东西。
    • 我现在从您的查询中收到错误“缺少关键字”
    • 我可以使用这段代码,但仍然不是我需要的。
    • 用 table1 中的 3 个不同的 col1 更新了代码,见这个
    【解决方案3】:

    下面的查询可以解决问题

        with t2 as (
        select c3
          from t2
         where c3 in ('COD1', 'COD2', 'COD3', 'COD4')
        )
       ,t3 as (
        select distinct
               c1
              ,c2
          from t1
       )    
      ,t_all as (
       select t3.c1
             ,t3.c2
             ,t2.c3
         from t3
             ,t2 
       )
       select t1.c1
             ,t1.c2
             ,t_all.c3
         from t_all left join t1 on 
              t1.c1 = t_all.c1 and t1.c2 = t_all.c2 and t1.c3 = t_all.c3
    

    【讨论】:

    • 如何使用。我得到“递归 WITH 子句必须有列别名列表”
    • 好的,我找到了如何使用它。我会在一分钟内检查它是否正确。谢谢
    • 这是不对的。我为每个 column1-column3 对获得多个条目
    • @LiefLayer 更新了查询。我用你的数据进行了测试,它产生了你现在期望的准确结果。
    【解决方案4】:

    您正在寻找 partition outer join 2004 年以来的“新”功能,但仍未被广泛使用。

    期望table1 包含column3 的所有值至少一个值,但column2 是稀疏的并且必须填充。 (注意,你甚至根本不需要table2

    查询很简单,因为您希望 column2 在添加时为 NULL,您必须使用 casestatement 重置它:

    select 
      tab.column1, 
      case when tab.column1 is NOT NULL then tab.column2 end column2, 
      c3.column3
    from tab
    partition by (column2)
    right outer join 
    (select distinct column3 from tab) c3
    on tab.column3 = c3.column3
    order by tab.column2, c3.column3;
    

    这会按要求生成数据:

    COLUMN COL COLU
    ------ --- ----
    000001 ABC COD1
    000001 ABC COD2
               COD3
               COD4
               COD1
               COD2
    000002 BCD COD3
               COD4
    000003 EDF COD1
               COD2
    000003 EDF COD3
               COD4
    000004 FGH COD1
    000004 FGH COD2
    000004 FGH COD3
    000004 FGH COD4
    

    请注意,手动解决方案(即在分区外连接之前)是从table1 获取第2 列和第3 列的所有组合 - 请参阅下面的子查询comb

    第二步简单的outer joincomb到你的餐桌

    with col2 as(
    select distinct column2 from tab),
    col3 as (
    select distinct column3 from tab),
    comb as (
    select *
    from col2 cross join col3)
    select tab.column1, tab.column2, comb.column3 from comb
    left outer join tab 
    on comb.column2 = tab.column2 and comb.column3 = tab.column3
    order by comb.column2, comb.column3
    ;
    

    这给出了相同的结果。

    【讨论】:

      猜你喜欢
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多