【问题标题】:Flat Join of two tables两个表的平面连接
【发布时间】:2012-05-08 16:05:20
【问题描述】:

对于这两个表:

CREATE TABLE TEST1 ( ID  INTEGER ,key  VARCHAR(50),VALUE1 VARCHAR(50));
CREATE TABLE TEST2 ( ID  INTEGER ,key  VARCHAR(50),VALUE2 VARCHAR(50));

表1:

130,    'HANSEN',   'STREET1'
130,    'HANSEN',   'STREET2'
130,    'HANSEN',   'STREET3'
120,    'HANSEN',   'STREET5'
120,    'HANSEN',   'STREET6'

表2:

130,    'HANSEN',   'ZIP1'
130,    'HANSEN',   'ZIP2'
130,    'HANSEN',   'ZIP3'
120,    'HANSEN',   'ZIP4'
120,    'HANSEN',   'ZIP5'

是否可以得到如下输出:

130,    'HANSEN',   'ZIP1','STREET1'
130,    'HANSEN',   'ZIP2','STREET2'
130,    'HANSEN',   'ZIP3','STREET3'
120,    'HANSEN',   'ZIP4','STREET5'
120,    'HANSEN',   'ZIP5','STREET6'

尝试在 id,key 上使用内部连接,但我得到笛卡尔积
感谢您的帮助。

帮助脚本(如果有人愿意测试的话):

DROP TABLE TEST1;
DROP TABLE TEST2;

CREATE TABLE TEST1 ( ID  INTEGER ,key  VARCHAR(50),VALUE1 VARCHAR(50));
CREATE TABLE TEST2 ( ID  INTEGER ,key  VARCHAR(50),VALUE2 VARCHAR(50));

INSERT INTO TEST1 VALUES (130,  'HANSEN',   'STREET1');
INSERT INTO TEST1 VALUES (130,  'HANSEN',   'STREET2');
INSERT INTO TEST1 VALUES (130,  'HANSEN',   'STREET3');
INSERT INTO TEST1 VALUES (120,  'HANSEN',   'STREET5');
INSERT INTO TEST1 VALUES (120,  'HANSEN',   'STREET6');

INSERT INTO TEST2 VALUES (130,  'HANSEN',   'ZIP1');
INSERT INTO TEST2 VALUES (130,  'HANSEN',   'ZIP2');
INSERT INTO TEST2 VALUES (130,  'HANSEN',   'ZIP3');
INSERT INTO TEST2 VALUES (120,  'HANSEN',   'ZIP4');
INSERT INTO TEST2 VALUES (120,  'HANSEN',   'ZIP5');

【问题讨论】:

  • @Vash:不,这不是笛卡尔连接。显然 OP 需要加入 ROW NUMBER。可能会完成,具体取决于 RDBMS。
  • @Vash: 想要的输出不是笛卡尔连接
  • 您刚刚说明您需要两列:一列用于街道,第二列用于邮编。逗号是列的分隔符。 'ZIP1','STREET1'
  • @PabloSantaCruz,是的,我尽快删除了评论。但对你来说慢了。行号是很好的提示。
  • 您如何知道TEST1 中的哪一行与TEST2 中的哪一行相匹配?为什么STREET1 匹配ZIP1 而不是ZIP2?或者哪些行(具有相同的ID)匹配在一起是否重要?如果一个或另一个表的特定 ID 的行数比另一个表多,会发生什么情况?

标签: sql oracle inner-join


【解决方案1】:

应该这样做:

with t1 as (
    select id, 
           key, 
           value1,
           row_number() over (partition by id order by key, value1) as rn
    from test1
), 
t2 as (
    select id, 
           key, 
           value2,
           row_number() over (partition by id order by key, value2) as rn
    from test2
)
select t1.id, 
       t2.key, 
       t2.value2||','||t1.value1
from t1
  join t2 on t1.id = t2.id and t1.key = t2.key and t1.rn = t2.rn
order by 1 desc, 3 asc

【讨论】:

  • @user648026:向我们展示解释计划。表上定义了哪些索引?
  • 从 test2 中选择 XXX,从 test1 中选择 XXX - 会创建完整的表访问权限吗?除非你有 ID 索引..
  • @user648026:id, key, value 上的索引可能也会有所帮助。
【解决方案2】:

它并不漂亮,根据 Oracle 为您提供结果集的顺序,您可能会得到奇怪的结果,但您可以尝试:

select t1.id, t1.key, t1.value1, t2.value2 
  from
     (select rownum rn, id, key, value1 from test1) t1 
          inner join
     (select rownum rn, id, key, value2 from test2) t2
          using (rn)

如果您需要按照您的建议“合并”这两个表,我会尝试添加一些“合并”列来这样做,而不是使用这种方法。

【讨论】:

  • @user648026:哦,是的!确实很危险。
【解决方案3】:

不。没有办法可靠地获得您想要的输出。

您的数据模型似乎缺少一些信息。即某种方式将行从测试 1 链接到测试 2.. 您目前拥有的 id/key 不够唯一。

我认为你能做的最好的事情就是

select *
from test1 
inner join test2 using (id,key)
order by 1 desc,2,3,4

它给出了输出

130 HANSEN  STREET1 ZIP1
130 HANSEN  STREET1 ZIP2
130 HANSEN  STREET1 ZIP3
130 HANSEN  STREET2 ZIP1
130 HANSEN  STREET2 ZIP2
130 HANSEN  STREET2 ZIP3
130 HANSEN  STREET3 ZIP1
130 HANSEN  STREET3 ZIP2
130 HANSEN  STREET3 ZIP3
120 HANSEN  STREET5 ZIP4
120 HANSEN  STREET5 ZIP5
120 HANSEN  STREET6 ZIP4
120 HANSEN  STREET6 ZIP5

【讨论】:

    猜你喜欢
    • 2016-10-03
    • 2023-04-09
    • 1970-01-01
    • 2012-03-29
    • 2023-03-14
    • 2015-02-24
    • 2016-12-09
    相关资源
    最近更新 更多