【问题标题】:How to join table records based on the state?如何根据状态连接表记录?
【发布时间】:2018-12-03 14:33:53
【问题描述】:

我有一个必须根据状态连接到另一个表的表。以下是表1数据的示例:

ROWID  STATE 
 34     TX
 56     NY
 67     WA
 89     TX

表一中的每一行都有状态值。表 2 中每个州都有两条记录。这是一个例子:

ROWID   STATE       NAME  
 19      TX     Chuck, Brown
 20      TX     Nick, Johnes 

正如您在表 2 中看到的,德克萨斯州有两条记录。如果我使用Left Outer Join 并尝试做这样的事情:

LEFT OUTER JOIN Table 2 TB2
   ON TB1.STATE = TB2.SATE

那么输出会是这样的:

34 TX Chuck, Brwon
34 TX Nick, Johnes
89 TX Chuck, Brwon
89 TX Nick, Johnes

每一行都是重复的,因为我在表 1 中有两条德州记录。然后我在德克萨斯州的表 2 中有两条记录。我想看到的是这样的:

ROWID   STATE     NAME 1         NAME 2
 34      TX    Chuck, Brwon    Nick, Johnes

基本上我想将两行合并为一,然后加入表 1。我最近开始从事这个项目,我们使用 Oracle 数据库。如果有人知道实现这一目标的好方法,请告诉我。谢谢。

【问题讨论】:

  • 每个State 是否总是有0、1 或2 个Name 记录?或者数字在设计时是可变的和/或未知的?是什么决定了NameName 1 还是Name 2
  • @APC 表 2 中的状态总是有两条记录。没有什么特别的决定 Name 1Name 2。总是应该有两个名字。我所需要的只是将它们组合起来(例如像这样Josh, Brown & Micky, Butt 连接)。
  • 如果您在表 1 中有两条 TX 记录,但在最终结果中您只有一条结果记录,那又如何呢?应该如何正确选择TX记录?或者您想在按 ROWID 排序时将名字与第一个 TX 记录连接起来,将第二个名字与第二个 TX 记录连接起来?
  • @Sentinel 如果您仔细查看我上面的示例,您会发现当前带有左外连接的代码是重复行。我想将同一状态的名称合并到一行中。因此,例如在表 2 中应该有一个 TX 记录,名称应该是这样的 Chuck, Brwon & Nick, Johnes 或两列名称 1 和名称 2。我希望这将帮助您理解我想要实现的目标。
  • 不需要外连接,除非您想从 table1 返回所有记录,即使 table2 中不存在匹配的记录。请参阅下面的答案,它提供了所需的输出,但不使用外连接。

标签: oracle oracle11g left-join oracle-sqldeveloper


【解决方案1】:

根据示例所需的输出,我将输出限制为 table1 中的第一个状态实例,并按 ID 对旋转后的名称进行排序,尽管这恰好与给定示例数据的名称字段的字母顺序匹配。

看到这个SQL Fiddle

Oracle 11g R2 架构设置

请注意,在 Oracle 中,ROWID 是保留名称,因此我将其更改为 ID。

CREATE TABLE Table1
    ("ID" number, "STATE" varchar2(2))
;

INSERT ALL 
    INTO Table1 ("ID", "STATE")
         VALUES (34, 'TX')
    INTO Table1 ("ID", "STATE")
         VALUES (56, 'NY')
    INTO Table1 ("ID", "STATE")
         VALUES (67, 'WA')
    INTO Table1 ("ID", "STATE")
         VALUES (89, 'TX')
SELECT * FROM dual
;

CREATE TABLE Table2
    ("ID" number, "STATE" varchar2(2), "NAME" varchar2(12))
;

INSERT ALL 
    INTO Table2 ("ID", "STATE", "NAME")
         VALUES (19, 'TX', 'Chuck, Brown')
    INTO Table2 ("ID", "STATE", "NAME")
         VALUES (20, 'TX', 'Nick, Johnes')
SELECT * FROM dual
;

查询 1

select t1.id
     , t2.state
     , t2.name
  from (select min(id) id, state from table1 group by state) t1
  join table2 t2
    on t1.state = t2.state

Results

| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |

查询 2

with t1(id, state) as (
  select min(id) id, state from table1 group by state
), t2 as (   
  select state
       , row_number() over (partition by state order by name) rn
       , name
    from table2
)
select t1.id
     , pvt.*
  from t1
  join t2 pivot (max(name) for rn in (1 name_1,2 name_2)) pvt
    on t1.state = pvt.state

Results

| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |

【讨论】:

    【解决方案2】:

    正如您在问题下的一个 cmets 中所说,您将接受单个 串联 NAME 列,这是一个选项;我使用 CTE 创建表,因此您需要从第 13 行开始。

    SQL> with
      2  t1 (rid, state) as
      3    (select 34, 'TX' from dual union all
      4     select 56, 'NY' from dual union all
      5     select 67, 'WA' from dual union all
      6     select 89, 'TX' from dual
      7    ),
      8  t2 (rid, state, name) as
      9    (select 19, 'TX', 'Chuck, Brown' from dual union all
     10     select 20, 'TX', 'Nick, Johnes' from dual
     11    ),
     12  -- start here
     13  it2 as
     14    (select state, listagg(name, ' & ') within group (order by null) name
     15     from t2
     16     group by state
     17    )
     18  select min(t1.rid) rid,
     19    t1.state,
     20    it2.name
     21  from t1 join it2 on t1.state = it2.state
     22  and t1.state = 'TX'
     23  group by t1.state, it2.name;
    
           RID ST NAME
    ---------- -- ------------------------------
            34 TX Chuck, Brown & Nick, Johnes
    
    SQL>
    

    【讨论】:

      猜你喜欢
      • 2015-11-01
      • 2021-09-08
      • 2014-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多