【问题标题】:SQL Join with when data matches数据匹配时的 SQL Join
【发布时间】:2017-04-12 16:23:43
【问题描述】:

我有两个表 table1 和 table2

CREATE TABLE TABLE1 (
   EMPLID VARCHAR2(11) NOT NULL,
   COMPANY VARCHAR2(3) NOT NULL,
   EMPL_RCD SMALLINT NOT NULL,
   BALANCE_ID VARCHAR2(2) NOT NULL,
   BALANCE_YEAR SMALLINT NOT NULL,
   BALANCE_QTR SMALLINT NOT NULL,
   BALANCE_PERIOD SMALLINT NOT NULL,
   SPCL_BALANCE VARCHAR2(1) NOT NULL,
   ERNCD VARCHAR2(3) NOT NULL,
   HRS_QTD DECIMAL(13, 2) NOT NULL,
   GRS_QTD DECIMAL(13, 2) NOT NULL,
   HRS_YTD DECIMAL(13, 2) NOT NULL,
   GRS_YTD DECIMAL(13, 2) NOT NULL,
   HRS_MTD DECIMAL(13, 2) NOT NULL,
   GRS_MTD DECIMAL(13, 2) NOT NULL);

CREATE TABLE TABLE2(EMPLID VARCHAR2(11) NOT NULL,
   COMPANY VARCHAR2(3) NOT NULL,
   BALANCE_ID VARCHAR2(2) NOT NULL,
   BALANCE_YEAR SMALLINT NOT NULL,
   BALANCE_QTR SMALLINT NOT NULL,
   BALANCE_PERIOD SMALLINT NOT NULL,
   EMPL_RCD SMALLINT NOT NULL,
   SPCL_BALANCE VARCHAR2(1) NOT NULL,
   ERNCD VARCHAR2(3) NOT NULL,
   HRS_YTD DECIMAL(13, 2) NOT NULL,
   HRS_QTD DECIMAL(13, 2) NOT NULL,
   HRS_MTD DECIMAL(13, 2) NOT NULL,
   GRS_YTD DECIMAL(13, 2) NOT NULL,
   GRS_QTD DECIMAL(13, 2) NOT NULL,
   GRS_MTD DECIMAL(13, 2) NOT NULL);

我想编写一个查询来从 table1 和 table2 中获取数据,返回 table1 中的所有行和 table2 中的“匹配”值 匹配值意味着,当 EMPLID、ERNCD 匹配时,它应该显示行。 EMPLID 和 SPCL_BALANCE 之间的所有字段都是键。

table1 的样本数据:

INSERT INTO table1 VALUES('XX','C','0','CY','2015','2','4','Y','XYZ','0','0','0','0','100001','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2015','2','5','Y','XYZ','0','0','0','0','100002','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2015','2','6','Y','XYZ','0','0','0','0','100003','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2015','3','7','Y','XYZ','0','0','0','0','100004','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2015','3','9','Y','XYZ','0','0','0','0','100005','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2015','4','10','Y','XYZ','0','0','0','0','100006','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2015','4','12','Y','XYZ','0','0','0','0','100001','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2016','1','1','Y','XYZ','0','0','0','0','100002','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2016','1','2','Y','XYZ','0','0','0','0','100003','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2016','1','3','Y','XYZ','0','0','0','0','100004','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2016','2','4','Y','XYZ','0','0','0','0','100005','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2016','2','6','Y','XYZ','0','0','0','0','100006','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2016','2','6','Y','DCP','0','100001','0','100001','0','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2016','2','6','Y','SAV','0','100002','0','100002','0','0');
INSERT INTO table1 VALUES('XX','C','0','CY','2016','2','6','Y','SUP','0','100003','0','100003','0','96949.98');
INSERT INTO table1 VALUES('XX','C','0','FY','2016','4','11','Y','PER','0','100004','0','100004','0','0');
INSERT INTO table1 VALUES('XX','C','0','FY','2016','4','11','Y','RET','0','100005','0','100005','0','0');
INSERT INTO table1 VALUES('XX','C','0','FY','2016','4','11','Y','SUM','0','100006','0','100006','0','0');

表 2 的示例数据

INSERT INTO table2 VALUES('XX','C','CY','2015','2','4','0','Y','XYZ','0','0','176','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2015','2','5','0','Y','XYZ','0','0','176','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2015','2','6','0','Y','XYZ','0','0','168','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2015','3','7','0','Y','XYZ','0','0','360','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2015','3','9','0','Y','XYZ','0','0','168','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2015','4','10','0','Y','XYZ','0','0','352','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2015','4','12','0','Y','XYZ','0','0','168','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2016','1','1','0','Y','XYZ','0','0','184','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2016','1','2','0','Y','XYZ','0','0','168','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2016','1','3','0','Y','XYZ','0','0','168','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2016','2','4','0','Y','XYZ','0','0','352','0','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2016','2','5','0','Y','DCP','0','0','0','100001','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2016','2','5','0','Y','SAV','0','0','0','100002','0','0')
INSERT INTO table2 VALUES('XX','C','CY','2016','2','5','0','Y','SUP','0','0','0','100003','0','0')
INSERT INTO table2 VALUES('XX','C','FY','2016','4','10','0','Y','PER','0','0','0','100004','0','0')
INSERT INTO table2 VALUES('XX','C','FY','2016','4','10','0','Y','RET','0','0','0','100005','0','0')

我想编写一个查询,只要 EMPLID 和 ERNCD 匹配,就显示 table1 中的所有 18 行,而不管其他键是否匹配。

输出样本

t1.emplid   t2.emplid   t1.company  t2.compnay  t1.empl_rcd t2.empl_rcd t1.balance_id   t2.balance_id   t1.balance_year t2.balance_year t1.balance_qtr  t2.balance_qtr  t1.balance_period   t2.balance_period   t1.erncd    t2.erncd
10011024    10011024    UCS UCS 0   0   CY  CY  2015    2015    2   2   4   4   ACA ACA
10011024    10011024    UCS UCS 0   0   CY  CY  2015    2015    2   2   5   5   ACA ACA
10011024    10011024    UCS UCS 0   0   CY  CY  2015    2015    2   2   6   6   ACA ACA
10011024    10011024    UCS UCS 0   0   CY  CY  2015    2015    3   3   7   7   ACA ACA
10011024    10011024    UCS UCS 0   0   CY  CY  2015    2015    3   3   9   9   ACA ACA
10011024    10011024    UCS UCS 0   0   CY  CY  2015    2015    4   4   10  10  ACA ACA
10011024    10011024    UCS UCS 0   0   CY  CY  2015    2015    4   4   12  12  ACA ACA
10011024    10011024    UCS UCS 0   0   CY  CY  2016    2016    1   1   1   1   ACA ACA
10011024    10011024    UCS UCS 0   0   CY  CY  2016    2016    1   1   2   2   ACA ACA
10011024    10011024    UCS UCS 0   0   CY  CY  2016    2016    1   1   3   3   ACA ACA
10011024    10011024    UCS UCS 0   0   CY  CY  2016    2016    2   2   4   4   ACA ACA
10011024    NULL    UCS NULL    0   NULL    CY  NULL    2016    NULL    2   NULL    6   NULL    ACA NULL
10011024    10011024    UCS UCS 0   0   CY  CY  2016    2016    2   2   6   5   DCP DCP
10011024    10011024    UCS UCS 0   0   CY  CY  2016    2016    2   2   6   5   SAV SAV
10011024    10011024    UCS UCS 0   0   CY  CY  2016    2016    2   2   6   5   SUP SUP
10011024    10011024    UCS UCS 0   0   FY  FY  2016    2016    4   4   11  10  PER PER
10011024    10011024    UCS UCS 0   0   FY  FY  2016    2016    4   4   11  10  RET RET
10011024    NULL    UCS NULL    0   NULL    CY  NULL    2016    NULL    4   NULL    11  NULL    SUM NULL

我希望这会有所帮助。我目前正在使用下面的 sql 但没有获取所有行:

  FROM 
        (
      select  EBCS1.EMPLID ,EBCS1.COMPANY ,EBCS1.BALANCE_ID ,EBCS1.BALANCE_YEAR ,EBCS1.BALANCE_QTR ,
    EBCS1.BALANCE_PERIOD ,EBCS1.EMPL_RCD ,EBCS1.SPCL_BALANCE ,EBCS1.ERNCD ,EBCS1.HRS_YTD ,EBCS1.HRS_QTD ,EBCS1.HRS_MTD ,
    EBCS1.GRS_YTD ,EBCS1.GRS_QTD ,EBCS1.GRS_MTD 
             row_number() over (partition by EBCS1.EMPLID order by case when EBCS1.EMPLID is not null then 0 else 1 end asc, EBCS1.ERNCD) rn
      from table1 EBCS1 left join 
      (select distinct EMPLID,EMPL_RCD, COMPANY, BALANCE_ID,BALANCE_YEAR,BALANCE_QTR,BALANCE_PERIOD,ERNCD,SPCL_BALANCE from table2) EBPS1 on 
      EBCS1.EMPLID=EBPS1.EMPLID AND EBCS1.BALANCE_ID=EBPS1.BALANCE_ID  and EBCS1.COMPANY=EBPS1.COMPANY AND EBCS1.ERNCD=EBPS1.ERNCD and EBCS1.BALANCE_PERIOD = EBPS1.BALANCE_PERIOD
    AND EBCS1.BALANCE_QTR = EBPS1.BALANCE_QTR AND EBCS1.EMPL_RCD = EBPS1.EMPL_RCD AND EBCS1.BALANCE_YEAR = EBPS1.BALANCE_YEAR 
    AND EBCS1.SPCL_BALANCE =EBPS1.SPCL_BALANCE  ) EBCS
         LEFT OUTER JOIN 
         (
        select  EBPS1.EMPLID ,EBPS1.COMPANY ,EBPS1.BALANCE_ID ,EBPS1.BALANCE_YEAR ,EBPS1.BALANCE_QTR ,
    EBPS1.BALANCE_PERIOD ,EBPS1.EMPL_RCD ,EBPS1.SPCL_BALANCE ,EBPS1.ERNCD ,EBPS1.HRS_YTD ,EBPS1.HRS_QTD ,EBPS1.HRS_MTD ,
    EBPS1.GRS_YTD ,EBPS1.GRS_QTD ,EBPS1.GRS_MTD,
             row_number() over (partition by EBPS1.EMPLID order by case when EBPS1.EMPLID is not null then 0 else 1 end asc, EBPS1.ERNCD) rn
      from table2 EBPS1  left join (select distinct EMPLID,EMPL_RCD,COMPANY,BALANCE_ID,BALANCE_YEAR,BALANCE_PERIOD,ERNCD,SPCL_BALANCE,BALANCE_QTR
      from table1) EBCS1 ON
      EBCS1.EMPLID=EBPS1.EMPLID AND EBCS1.BALANCE_ID=EBPS1.BALANCE_ID  and EBCS1.COMPANY=EBPS1.COMPANY AND EBCS1.ERNCD=EBPS1.ERNCD and EBCS1.BALANCE_PERIOD = EBPS1.BALANCE_PERIOD
    AND EBCS1.BALANCE_QTR = EBPS1.BALANCE_QTR AND EBCS1.EMPL_RCD = EBPS1.EMPL_RCD AND EBCS1.BALANCE_YEAR = EBPS1.BALANCE_YEAR AND EBCS1.SPCL_BALANCE =EBPS1.SPCL_BALANCE  ) EBPS
      ON ( EBPS.EMPLID=EBCS.EMPLID AND EBPS.COMPANY=EBCS.COMPANY AND EBCS.rn=EBPS.rn ) 

使用下面的查询输出:

XX1 CY  CY  2   2   1   1   ACA ACA
XX1 CY  CY  3   3   1   1   ACA ACA
XX1 CY  CY  4   4   2   2   ACA ACA
XX1 CY      6   0   2   0   ACA  
XX1 CY      6   0   2   0   DCP  
XX1 CY      6   0   2   0   SAV  
XX1 CY      6   0   2   0   SUP  
XX1 FY      11  0   4   0   SAF 

预期输出:

XX1 CY  CY  2   2   1   1   ACA ACA
XX1 CY  CY  3   3   1   1   ACA ACA
XX1 CY  CY  4   4   2   2   ACA ACA
XX1 CY  NULL    6   0   2   0   ACA NULL
XX1 CY  CY  6   2   2   5   DCP DCP
XX1 CY  CY  6   2   2   5   SAV SAV
XX1 CY  CY  6   2   2   5   SUP SUP
XX1 FY  FY  11  4   10  10  SAF SAF

【问题讨论】:

  • 您似乎知道答案,只需在 t1.EMPLID = t2.EMPLID 和 t1.ERNCD = t2.ERNCD 上执行 Table1 t1 left join Table2 t2
  • @EvanSteinbrenner 这个问题是对这个original question 的补充。连接“通常”应该在每个表的所有前 8 个字段上。因此,EMPLID 和 ERNCD 上的简单“左连接”会产生大量重复项。
  • 我花费更多时间纠正测试数据而不是专注于您的问题 :-) 示例输出与您发布的示例数据不相关。我应该如何使用该示例输出来验证我的提案?

标签: sql oracle join left-join


【解决方案1】:

我想到的唯一想法是:

  select t1.emplid,t1.balance_id,t2.balance_id,t1.balance_period,t2.balance_period,t1.balance_qtr,t2.balance_qtr, t1.erncd,t2.erncd
    from table1 t1 join table2 t2 
      on t1.emplid=t2.emplid
     and t1.company=t2.company
     and t1.empl_rcd=t2.empl_rcd
     and t1.balance_id=t2.balance_id
     and t1.balance_year=t2.balance_year
     and t1.balance_qtr=t2.balance_qtr
     and t1.balance_period=t2.balance_period
     and t1.spcl_balance=t2.spcl_balance
     and t1.erncd=t2.erncd
   union all
  select t1.emplid, 
         t1.balance_id, null balance_id, 
         t1.balance_period, null balance_period,
         t1.balance_qtr, null balance_qtr, 
         t1.erncd, null erncd
    from table1 t1 
         left join (select * from table2 t3
                     where not exists 
                          ( select 1 from table1 t4
                             where t3.emplid=t4.emplid
                               and t3.company=t4.company
                               and t3.empl_rcd=t4.empl_rcd
                               and t3.balance_id=t4.balance_id
                               and t3.balance_year=t4.balance_year
                               and t3.balance_qtr=t4.balance_qtr
                               and t3.balance_period=t4.balance_period
                               and t3.spcl_balance=t4.spcl_balance
                         )
                    ) t3
                on t1.emplid=t3.emplid
               and t1.erncd=t3.erncd
   where not exists 
     ( select 1 from table2 t2
        where t1.emplid=t2.emplid
          and t1.company=t2.company
          and t1.empl_rcd=t2.empl_rcd
          and t1.balance_id=t2.balance_id
          and t1.balance_year=t2.balance_year
          and t1.balance_qtr=t2.balance_qtr
          and t1.balance_period=t2.balance_period
          and t1.spcl_balance=t2.spcl_balance
     );

在查询的第一部分,我将返回所有完全匹配的行。在第二个中,我返回 table1 与 table2 连接的所有行,具有相同的 emplid 和 erncd(但仅在不匹配的记录上)。

如果这不符合您的要求,您能否在示例中添加 table2 行和完整的预期结果?

我不清楚第二个联合是否会根据您的数据返回重复项。

【讨论】:

  • 以前的代码似乎不完整。你能检查一下吗?
  • 删除了最后一个“和”
  • 谢谢@Insac,我已经更新了,实际上表格要复杂得多,我手头的时间很短。对于给您带来的所有不便,我深表歉意。我已经添加了使用您的查询收到的输出与其中一名员工的预期输出。请检查
  • 您能否同时发布与该员工相关的两个表格行? (而且我们在日常任务之间的时间很短,所以输入的数据越好,答案就越快)。另外,请不要假设我会回答您的问题。这不是“InsacOverflow”:-) 如果您成功创建了一个独立的查询,其他人很可能会尝试回答您的问题。跨度>
猜你喜欢
  • 1970-01-01
  • 2018-12-14
  • 2021-12-19
  • 1970-01-01
  • 2019-07-13
  • 2019-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多