多个外连接返回一个结果

时间:2014-03-07 03:45:20

标签: sql left-join outer-join

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

我回答了这个问题: 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)

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

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

2 个答案:

答案 0 :(得分: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”两者的连接(或多个连接)中使用这些派生表中的任何一个。在下面的示例中,我在公用表表达式中使用第二个语句(上面),并在两个列上连接。

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表从根本上简化你的生活。直接引用“名称”和“trm”。 (我忽略了“lex”表,其目的简直莫名其妙。)

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

根据目的,对于针对该表的某些查询,您可能不需要任何连接。

答案 1 :(得分:0)

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

希望这有助于某人!