条件联盟

时间:2012-12-02 15:18:16

标签: sql union conditional-statements

假设我在UNION中有三个子查询。

select * from (
    select nr, pos, '1' from foo
    union all
    select nr, pos, '2' from bar
    union all
    select nr, pos, '3' from foobar
)

我需要的是从foobar返回行的结果 仅当第一个子查询(来自nr)未返回foo值时。

nr列必须是唯一的条件,而不是整行, 所以UNION无济于事。我是对的吗?

抱歉,我不知道如何更好地解释这一点。

4 个答案:

答案 0 :(得分:2)

在最后where添加select子句,只有前两个查询没有结果时才返回结果。请参阅下面的更新查询:

select nr, pos, '1' from foo
union all
select nr, pos, '2' from bar
union all
select nr, pos, '3' from foobar fb
 where not exists (select 1 from foo f where fb.nr = f.nr)
   and not exists (select 1 from bar b where fb.nr = b.nr)

答案 1 :(得分:1)

也许是这样的伎俩:

select distinct min(x), nr, pos from (
    select nr, pos, '1' as x from foo
    union all
    select nr, pos, '2' from bar
    union all
    select nr, pos, '3' from foobar
)
group by nr, pos

答案 2 :(得分:0)

您似乎需要:

SELECT *
  FROM (SELECT nr, pos, '1' AS code FROM foo
        UNION ALL
        SELECT nr, pos, '2' AS code FROM bar
        UNION ALL
        SELECT nr, pos, '3' AS code
          FROM foobar
         WHERE nr NOT IN (SELECT nr FROM foo)
       )

您可以扩展该处理,以便bar中的项目未被选中,除非它们未在foo中列出,并且foobar中的项目未被选中,除非它们不是列在foobar中。显然,您可以选择code以外的名称(可能是source)作为数值的列名称,但您应该为其提供名称。

答案 3 :(得分:0)

如果您正在使用的SQL产品支持排名功能,您可以尝试以下方法:

SELECT nr, pos, src
FROM (
  SELECT *, RANK() OVER (PARTITION BY nr ORDER BY src) AS rnk
  FROM (
    SELECT nr, pos, '1' AS src FROM foo
    UNION ALL
    SELECT nr, pos, '3' AS src FROM foobar
  ) s
) s
WHERE rnk = 1
UNION ALL
SELECT nr, pos, '2' AS src FROM bar
;

最里面的子查询联合来自foofoobar的行。中间层子查询根据提供它们的源表对nr值进行排名:

    如果在foobar中找不到相应的1值,
  • 来自nr的行的排名为foo;

  • 否则foo行排名为1

排名结果集在rnk = 1上过滤,然后与bar表联合(据我所知,无条件退回)。