【问题标题】:Multiple outer join return one result多个外连接返回一个结果
【发布时间】:2014-03-07 03:45:20
【问题描述】:

我有一个查询,我在其中执行三个左外连接,但我只想返回一个结果。

不久前我问过这个问题: Multiple Outer joins return top result

除此之外,我无法返回几个连接之外的第一行。

例如:

obj

|id    |  name  |
 1     |  bear  |
 2     |  cat   |
 3     |  moose |


obj_cn

|id    | obj_id | lex_id | ord
| 1    |  2     |  1     |  3
| 2    |  2     |  2     |  2
| 3    |  2     |  3     |  1
| 4    |  1     |  4     |  1

lex

| id   | trm_id |
| 1    |  2     |
| 2    |  1     |
| 3    |  4     |
| 4    |  3     |

trm

| id   | trm |
| 1    | puma|
| 2    | lion|
| 3    | brn |
| 4    |  cgr|

理想情况下,我想返回排序最低的术语,以及 objtermktr 表中的其他列(以及其他连接,此示例已简化)。

results

|id    | name   | trm
|1     | bear   | brn
|2     | cat    | cgr
|3     | moose  | NULL

我最初的想法是建立在上述问题的基础上,但是我在比较多个连接时遇到了麻烦,没有为 trm 返回 NULL 值或返回对象 id 2 三次(每个术语一次)。

这个查询不起作用,但这是我正在尝试的一种方式

SELECT id, name ,
,(select trm from trm t where t.id = a.id and r.ord=a.ord7) as term
from obj

left outer join
(select obj_id, lex_id, MIN(ord) ord7 from obj_cn group by obj_id, lex_id) a
on obj.id = a.obj_id

left outer join lex on a.lex_id = lex.trm_id
left outer join trm on lex.trm_id = trm.id)

任何指导将不胜感激。感谢阅读!

更新:我没有制作这个数据库,也无法对其进行重组。

【问题讨论】:

    标签: sql left-join outer-join


    【解决方案1】:

    如果您包含 CREATE TABLE 和 INSERT 语句,会很有帮助。

    create table obj (
      id integer primary key,
      name varchar(10) not null unique
      );
    
    insert into obj values
    (1, 'bear'),
    (2, 'cat'),
    (3, 'moose');
    
    create table trm (
      id integer primary key,
      trm varchar(10) not null unique
      );
    
    insert into trm values
    (1, 'puma'),
    (2, 'lion'),
    (3, 'brn'),
    (4, 'cgr');
    
    create table lex (
      id integer primary key,
      trm_id integer not null 
        references trm (id)
    );
    
    insert into lex values
    (1, 2),
    (2, 1),
    (3, 4),
    (4, 3);
    
    create table obj_cn (
      id integer primary key,
      obj_id integer not null
        references obj (id),
      lex_id integer not null
        references lex (id),
      ord integer not null
        check (ord > 0),
      unique (obj_id, lex_id)
    );
    
    insert into obj_cn values
    (1, 2, 1, 3),
    (2, 2, 2, 2),
    (3, 2, 3, 1),
    (4, 1, 4, 1);
    

    理想情况下,我想返回排序最低的术语,以及 objtermktr 表中的其他列(以及其他连接,本示例 已简化)。

    听起来像这样为您提供了最低排序的术语。

    select obj_id, min(ord) as ord
    from obj_cn
    group by obj_id;
    

    这个稍微复杂一点的版本将保留“obj”表中的所有行,您需要这些行才能获得所需的结果集。

    select obj.id as obj_id, min(ord) as ord
    from obj
    left join obj_cn on obj.id = obj_cn.obj_id
    group by obj.id
    

    您可以在“obj_id”或“obj_id”和“ord”的连接(或多个连接)中使用这些派生表中的任何一个。在下面的示例中,我在公用表表达式中使用了第二条 of 语句(上面),并在两列上连接。

    with min_ords as (
      select obj.id as obj_id, min(ord) as ord
      from obj
      left join obj_cn on obj.id = obj_cn.obj_id
      group by obj.id
    )
    select obj.id, obj.name, trm.trm
    from obj
    left join min_ords on min_ords.obj_id = obj.id 
    left join obj_cn on obj_cn.obj_id = obj.id and obj_cn.ord = min_ords.ord
    left join lex on lex.id = obj_cn.lex_id
    left join trm on trm.id = lex.trm_id
    order by id
    
    1  bear   brn
    2  cat    cgr
    3  moose
    

    由于您肯定对 obj.name 和 trm.trm 有一个唯一的约束,因此您可以通过重构 obj_cn 表从根本上简化您的工作。直接引用“name”和“trm”。 (我忽略了“lex”表,其目的简直令人费解。)

    name   trm   ord
    --
    cat    lion  3
    cat    puma  2
    cat    cgr   1
    bear   brn   1
    

    根据目的,您可能不需要任何连接来处理一些以该表为目标的查询。

    【讨论】:

    • 谢谢,我明白你所说的令人费解的结构是什么意思。但是我没有重构数据库的奢侈,只是从中获取数据的乐趣。
    • @user2856332:添加到回答中。
    • 嗯,我什至没有考虑派生表。感谢您的帮助。
    【解决方案2】:

    Arg,我将连接放在错误的位置。还在学习中...

    select obj.id, obj.name,
     (select trm.trm  from obj_cn F
     left outer join lex on f.lex_id = lex.id
     left outer join trm on lex.trm_id = trm.id
     where f.obj_id=C.obj_id and f.ord=C.ord7)
    
    from obj
    
    left outer join (select obj_id, MIN(ord) ord7 from obj_cn group by obj_id) C
    on obj.id = C.obj_id
    

    希望这对某人有所帮助!

    【讨论】:

      猜你喜欢
      • 2014-01-27
      • 2013-11-28
      • 1970-01-01
      • 1970-01-01
      • 2012-01-03
      • 1970-01-01
      • 2012-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多