【问题标题】:SQL Join with unique rows具有唯一行的 SQL 连接
【发布时间】:2016-10-14 08:46:14
【问题描述】:

我有两张桌子 表1

 - EMPLID XX_EMPLID GTN   DEDCD    EFFDT
     1     A1        102   XXYY     02-OCT-16
     1     A1        103   XXYZ     02-OCT-16

表2

  - EMPLID  DEDCD    EFFDT
     1       XXYA     02-OCT-16
     1       XXYZ     02-OCT-16

当我加入时,选择应该只返回两行,输出应该是

 - EMPLID   2.DEDCD    EFFDT        1.DEDCD
     1       XXYA     02-OCT-16      XXYY
     1       XXYZ     02-OCT-16      XXYZ

EMPLID,EFFDT 是关键。我不想加入 DEDCD,因为我需要看看有什么不同。请提出建议。

简单的连接总是会给我更多的行。我希望将行限制为 Table1 中的行数。我尝试了“右外连接”和“左外连接”但不起作用

经过一些帮助,我能够接近结果。但是,下面指出了我面临的一个问题

10008536    XXYZ    06-MAR-02   (XXYY)  06-MAR-02
10008536    (XXYY)  06-MAR-02   XXZZ    06-MAR-02

编辑 3

虽然我设法解决了我以前的问题,但我面临着另一个类似的问题。

两个表的键结构为 EMPLID、EMPL_RCD、BALANCE_ID、BALANCE_YEAR、BALANCE_QTR、BALANCE_PERIOD、ERNCD

我使用下面的 SQL 编写了一个查询来从两个表中获取值:

SELECT EBPS.EMPLID ,EBPS.BALANCE_ID ,EBPS.BALANCE_YEAR ,EBPS.BALANCE_QTR ,EBPS.BALANCE_PERIOD ,
EBPS.ERNCD ,EBCS.EMPLID ,EBCS.BALANCE_ID ,EBCS.BALANCE_YEAR ,EBCS.BALANCE_QTR ,
EBCS.BALANCE_PERIOD ,EBCS.ERNCD   
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 ,EBCS1.XX_EMPLOYEE_ID,
         row_number() over (partition by EBCS1.EMPLID,EBCS1.EMPL_RCD order by case when EBPS1.EMPLID is not null then 0 else 1 end asc,
         EBCS1.BALANCE_YEAR,EBCS1.BALANCE_QTR,EBCS1.BALANCE_PERIOD,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,EBPS1.EMPL_RCD order by case when EBCS1.EMPLID is not null then 0 else 1 end asc,
         EBCS1.BALANCE_YEAR,EBCS1.BALANCE_QTR,EBCS1.BALANCE_PERIOD,EBCS1.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 EBCS.EMPL_RCD=EBPS.EMPL_RCD   AND  EBCS.rn=EBPS.rn  )

但是,如果表 Table2 中缺少一行,我会得到不正确的结果。例如,如果员工在表 1 中有 16 行,在表 2 中有 15 行,并且对于某些行,ERNCD 匹配但 Period/Quarter 不匹配,在这种情况下,我想显示 Period/Quarter 不匹配但 ERNCD 匹配的数据。但目前,如果发生不匹配,行会变得杂乱无章。请让我知道是否有人能解决这个问题。如果您有任何问题,请告诉我。

【问题讨论】:

  • 正如你提到的JOIN 是答案尝试写一个,告诉你是否遇到任何问题
  • 是什么决定了table2中的XXYY行与table1中的XXYY行匹配?为什么不是 XXYZ?还有,table1的主键是什么?
  • 正如@Boneist 已经询问的那样,您需要澄清在第一个表中过滤掉 XXYZ 的标准。也许您需要 EMPLID 的最高 GTN 记录?
  • 问题是 table1 和 table2 上的 KEYS 不同。因此面临这个问题
  • @R_Prasad 如果他们有不同的键,请告诉我们两个表的键。但无论如何,你能用自然语言描述你需要什么输出吗?似乎是,除非您添加条件,否则没有明确的方法可以回答您的问题。

标签: sql oracle join


【解决方案1】:

好的,让我们看看这个答案是否符合您的要求。

SELECT a.EMPLID,a.DEDCD, to_char(a.EFFDT,'YYYY-MM-DD') EFFDT, b.DEDCD as DEDCD2,GTN 
   FROM 
   (
   select  EFFDT,GTN,EMPLID,DEDCD,
        row_number() over (partition by EMPLID order by DEDCD) rn
 from table1 ) A
    LEFT OUTER JOIN 
    (
   select  EFFDT,EMPLID,DEDCD,
        row_number() over (partition by EMPLID order by DEDCD) rn
 from table2       
    ) B
 ON ( A.EMPLID=B.EMPLID AND A.EFFDT=B.EFFDT AND a.rn=b.rn)

我在这里假设您只是对通过 EMPLID 和 EFFDT 链接的两个表的信息并排感兴趣,并且 table1 和 table2 将始终具有相同键的相同记录号。

我创建了一个示例供您在rextester.com 进行测试。

已编辑:新版本

我还尝试管理已在此处作为 cmets 提交的新“要求”。 它变得越来越复杂,但我希望这就是您所需要的:

 SELECT a.EMPLID,a.DEDCD, to_char(a.EFFDT,'YYYY-MM-DD') EFFDT, b.DEDCD as DEDCD2,GTN
    FROM 
    (
    select  t1.EFFDT,t1.GTN,t1.EMPLID,t1.DEDCD,
         row_number() over (partition by t1.EMPLID order by case when t2.EMPLID is not null then 0 else 1 end asc, t1.DEDCD) rn
  from table1 t1 left join (select distinct EMPLID,   EFFDT, DEDCD from    table2) t2 on  t1.EMPLID=t2.EMPLID AND t1.EFFDT=t2.EFFDT  and t1.DEDCD=t2.DEDCD
        ) A
     LEFT OUTER JOIN 
     (
    select  t2.EFFDT,t2.EMPLID,t2.DEDCD,
         row_number() over (partition by t2.EMPLID order by case when t1.EMPLID is not null then 0 else 1 end asc, t2.DEDCD) rn
  from table2 t2  left join (select distinct EMPLID,   EFFDT, DEDCD from    table1) t1 on  t1.EMPLID=t2.EMPLID AND t1.EFFDT=t2.EFFDT and t1.DEDCD=t2.DEDCD
     ) B
  ON ( A.EMPLID=B.EMPLID AND A.EFFDT=B.EFFDT AND a.rn=b.rn)

我创建了一个示例供您在 rextester.com 进行测试

【讨论】:

  • 但是,如果 Table1 有 3 行,而 Table2 有 2 ,我会得到不想要的结果。我们能克服吗?
  • 另外,如果 DEDCD 匹配,它应该显示在同一行中。
  • @R_Prasad 编辑后的版本是否满足您的新要求?
  • 感谢您的帮助。我只需要弄清楚一个问题。当 DEDCD 的值匹配时,它应该在同一行上。不知何故,对于某些值 DEDCD 不匹配,即使 emplid 在表中具有相同的 DEDCD。例如,如果员工在表 1 中有 XXYY & XXY1 和 XXYY & XXYZ ,则匹配 XXYY 的值应该在同一行中。但事实并非如此。
  • 我试图在 rextester(rextester.com/IKLWJ56409) 上测试你的场景,但它仍然可以正常工作,所以我一定是误解了。您能否对其进行修改、分叉并发布生成的链接,以便我了解您面临的问题?
【解决方案2】:

你可以通过使用简单的连接来实现,如下所示:

SELECT DISTINCT A.EMPLID, B.DEDCD AS DEDCD_2, A.EFFDT, A.DEDCD AS DEDCD_1
FROM table1 A
INNER JOIN table2 B ON A.EMPLID = B.EMPLID
    AND A.EFFDT = B.EFFDT

【讨论】:

  • Oracle 是否接受这些方括号作为分隔标识符?
  • 简单的连接总是会给我更多的行。我希望将行限制为 Table1 中的行数。我尝试了“右外连接”和“左外连接”但不起作用
  • 在示例中,所有 EFFDT 的值都相同,因此该查询不会删除重复项。
  • 您可以使用 DISTINCT 来避免重复行。
  • 我错了:我说的是“重复”,但它们只是“我们仍然不清楚为什么它们不应该出现在结果集中的附加行”。在示例中 DISTINCT 无济于事,因为结果的四行会有所不同(并且 OP 只想要其中的 2 个)
【解决方案3】:

我使用以下 SQL 来查找行。那些标记为错误问题的人需要先理解问题。如果我无法正确表达问题,请在否决之前告诉我。

SELECT DISTINCT DEDCD,EMPLID,DEDCD2 
 ,XX_GTN_nbr 
  FROM 
  (
  select  A.XX_GTN_nbr,A.EMPLID,A.DEDCD,B.DEDCD AS DEDCD2,
       row_number() over (partition by B.DEDCD
       order by A.EMPLID) rn
from PS_XX_PY50_GDED_RP A LEFT OUTER JOIN PS_GENL_DEDUCTION B
ON ( A.EMPLID=B.EMPLID AND A.EFFDT=B.EFFDT)
WHERE A.DEDCD<>' ' 
 ) WHERE RN=1; 

【讨论】:

  • 您是否对附加到问题的示例进行了测试?因为在我看来,当所有相关行的 EMPLID 为“1”时,order by A.EMPLID 不足以保证每次执行查询时都返回相同的行。
  • 好的,我找到了另一个测试Oracle SQL的站点(sqlfiddle似乎有问题)。你可以看到它here。我对这个查询的问题是它只依赖 table1 中行的“插入顺序”。这很少是一个好主意,因为某些管理任务(重建表)和应用程序任务(例如更新)可以更改顺序,从而更改查询结果。如果 GTN 是“全球交易号”,我建议您将其用作排序标准,以保证您的查询结果保持不变。
  • 顺便说一句,我刚刚意识到查询没有返回您想要的结果:它总是返回 EMPLID 列的 XXYZ(或 XXYY)
猜你喜欢
  • 1970-01-01
  • 2020-09-22
  • 1970-01-01
  • 2016-11-13
  • 2019-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多