Oracle 如何基于状态连接表记录?

Oracle 如何基于状态连接表记录?,oracle,oracle11g,left-join,oracle-sqldeveloper,Oracle,Oracle11g,Left Join,Oracle Sqldeveloper,我有一个表,它必须根据状态连接到另一个表。以下是表1数据的示例: ROWID STATE 34 TX 56 NY 67 WA 89 TX 表1中的每一行都有状态值。表2为每个州提供了两条记录。下面是一个例子: ROWID STATE NAME 19 TX Chuck, Brown 20 TX Nick, Johnes 如表2所示,德克萨斯州有两项记录。如果我使用左外连接并尝试执行以下操作

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

ROWID  STATE 
 34     TX
 56     NY
 67     WA
 89     TX
表1中的每一行都有状态值。表2为每个州提供了两条记录。下面是一个例子:

ROWID   STATE       NAME  
 19      TX     Chuck, Brown
 20      TX     Nick, Johnes 
如表2所示,德克萨斯州有两项记录。如果我使用
左外连接
并尝试执行以下操作:

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
然后输出将如下所示:

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数据库。如果有人知道实现这一目标的好方法,请让我知道。谢谢。

基于示例所需的输出,我将输出限制为表1中的第一个状态实例,并按ID对数据透视名称进行排序,尽管这恰好与给定示例数据的名称字段的alpha顺序相匹配

看到这个了吗

Oracle 11g R2架构设置

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
| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |
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
| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |
请注意,在Oracle中,ROWID是一个保留名称,因此我将其更改为ID

查询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
| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |
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
| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |

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
| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |
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
| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |
查询2

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
| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |
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
| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |

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
| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |
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
| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |

基于示例所需的输出,我将输出限制为表1中的第一个state实例,并按ID对数据透视名称进行排序,尽管这恰好与给定示例数据的name字段的alpha顺序相匹配

看到这个了吗

Oracle 11g R2架构设置

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
| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |
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
| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |
请注意,在Oracle中,ROWID是一个保留名称,因此我将其更改为ID

查询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
| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |
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
| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |

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
| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |
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
| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |
查询2

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
| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |
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
| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |

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
| ID | STATE |         NAME |
|----|-------|--------------|
| 34 |    TX | Nick, Johnes |
| 34 |    TX | Chuck, Brown |
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
| ID | STATE |       NAME_1 |       NAME_2 |
|----|-------|--------------|--------------|
| 34 |    TX | Chuck, Brown | Nick, Johnes |

正如你在问题下的一条评论中所说,你会接受一个单一的、连接的名称列,这里有一个选项;我使用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>

正如你在问题下的一条评论中所说,你会接受一个单一的、连接的名称列,这里有一个选项;我使用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>

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