查询输出

时间:2019-05-19 04:56:36

标签: sql

在一次采访中我被问到了这个问题。有2个表AB(它们只有一列id),其中包含以下数据

Table A
id
--
1
2
3

Table B
id
--
2
3
4

我需要产生以下类型的输出:

id | Present
------------
1  | "In A"
2  | "In A & In B"
3  | "In A & In B"
4  | "In B"

我提供了一个使用Union子句的解决方案,如下所示:

SELECT id, "In A" FROM A WHERE id NOT IN (SELECT id FROM B)
UNION
SELECT id, "In A & In B" WHERE id IN (SELECT id FROM B)
UNION
SELET id, "In B" WHERE id NOT IN (SELECT id FROM A)

在这种情况下,我使用3个单独的查询,并使用UNION进行组合。我认为Interview只是在寻找我的方法,而不是确切的查询。就是说,在我提出解决方案之后,他告诉我,至少有一个解决方案仅使用2个查询,并且还存在一个仅使用1个查询的解决方案。我尝试使用FULL OUTER JOIN,但无法提出具体建议。

那么获得以下输出的更好的查询是什么?采访者没有提到任何特定的数据库,所以我认为存在一个通用的解决方案。但是,如果查询特定于某种SQL风格就可以了。泛型会很好。

2 个答案:

答案 0 :(得分:5)

以下是与DBMS完全无关的答案(尽管由于缺乏对FULL OUTER JOIN的支持而无法在MySQL上使用):

SELECT COALESCE(A.id, B.id) AS id,
       CASE WHEN A.id IS NULL THEN 'In B'
            WHEN B.id IS NULL THEN 'In A'
            ELSE 'In A & In B' END AS Present
FROM A
FULL OUTER JOIN B ON B.id = A.id

输出:

id  present
1   In A
2   In A & In B
3   In A & In B
4   In B

该查询依赖于以下事实:如果外部联接的第二个表中没有匹配的行,则将JOIN编辑具有NULL值的行。因此,如果A.id IS NULL表示该值仅在表B中。如果B.id IS NULL则该值仅在表A中。并且如果两个id的值都不为NULL,则该值必须在两个表中都存在。

Oracle demo
SQL Server demo
PostgreSQL demo

答案 1 :(得分:0)

请勿为此使用full outer join!重复项或NULL值的行为不佳。我更喜欢union和聚合:

select id,
       (case when in_a = 1 and in_b = 1 then 'In A & In B'
             when in_a = 1 then 'In A'
             else 'In B'
        end) as present
from ((select id, 1 as in_a, 0 as in_b
       from a
      ) union  -- on purpose to remove duplicates
      (select id, 0, 1
       from b
      )
     ) ab
group by id;

在支持concat_ws()的数据库中,我将其简化为:

select id,
       concat_ws(' & ', in_a, in_b) as present
from ((select id, 'In A' as in_a, NULL as in_b
       from a
      ) union  -- on purpose to remove duplicates
      (select id, NULL, 'In B'
       from b
      )
     ) ab
group by id;