两个表,共同的行,以及其他

时间:2016-04-24 00:18:43

标签: mysql

两张桌子......

typedef Node* List

MySQL可以执行"加入"或者"联合"或者可以产生的任何查询:

Table 1:
Name Eyes Hair
---- ---- ----
Able Blue Cyan
Bill Cyan Blue
Sara Blue Blue

Table 2:
Name Hand Foot
---- ---- ----
Carl Left Right
Sara Right Left

4 个答案:

答案 0 :(得分:1)

这看起来像是一个“全外部”连接操作。不幸的是,MySQL没有为单个SELECT语句中的此操作提供语法。

幸运的是,可以使用两个SELECT语句模拟完整的外连接。

假设`name`列是主键,或者至少保证是唯一的......

给定名称基本上有三种可能的条件:

  • 两个(不幸名为)table1和table2(例如Sara)
  • 中都存在一行
  • table1中存在一行但不存在table2(例如Bill)
  • table2中存在一行但不存在table1(例如Carl)

(第四个条件,table1或table2中不存在名称值,我们不会关注自己,因为例如Javier没有行源。)

要获得满足第一个条件的行,我们可以使用INNER JOIN

第二个条件,我们可以通过将INNER JOIN转换为LEFT OUTER JOIN来在同一个SELECT中包含这些行。

第三个条件,我们需要一个单独的SELECT,它可以使用反连接模式。 (我们也可以使用NOT EXISTS或NOT IN,但这个特殊的规范是反连接非常适合的。)

我们可以使用UNION ALL设置操作来组合两个SELECT语句的结果。

我们首先获取行,然后处理表达式以获取列

第一个查询

SELECT t1.name 
  FROM table1 t1
  LEFT
  JOIN table2 t2
    ON t2.name = t1.name 

对于第二个查询

SELECT a2.name 
  FROM table2 a2
  LEFT
  JOIN table1 a1
    ON a1.name = a2.name
 WHERE a1.name IS NULL

这里的技巧(反连接模式)是WHERE子句中的条件,它排除了找到匹配项的任何行。所以我们留下来自a2的行,这些行在a1中没有匹配的行。

要使用UNION ALL集合操作来组合这些操作,列的列数和数据类型必须匹配。填写SELECT列表中的表达式,并添加ORDER BY子句,我们得到如下内容:

(未经测试)

 ( 
   SELECT t1.name 
        , t1.eyes
        , t1.hair
        , t2.hand
        , t2.foot
     FROM table1 t1
     LEFT
     JOIN table2 t2
       ON t2.name = t1.name
 )
 UNION ALL
 (
   SELECT a2.name 
        , a1.eyes
        , a1.hair
        , a2.hand
        , a2.foot
     FROM table2 a2
     LEFT
     JOIN table1 a1
       ON a1.name = a2.name
    WHERE a1.name IS NULL
 )
 ORDER BY `name`

请注意,为了获得那些有序的,我们在每个SELECT周围添加括号,并使用ORDER BY子句跟随最后一个。

同样,在MySQL中,这需要至少两个 SELECT语句。

还有其他查询模式可以返回等效结果,但这些模式需要 more 而不是两个SELECT。

答案 1 :(得分:0)

由于我无法对此进行测试,请注意第一次尝试时这可能不起作用,并且我需要你发布我得到的错误以便我知道(或你可以用一些虚拟数据创建一个SqlFiddle,但你应该能够这样做:

Select Name, Eyes, Hair, Null as Hand, Null as Foot from Table1
Union
Select Name, Null as Eyes, Null as Hair, Hand, Foot from Table2

但是,我认为您最好的办法是重新考虑当前数据库的设置方式。我几乎可以保证你会遇到问题。

答案 2 :(得分:0)

模式

insert table1 (name,eyes,hair) values
('Able','Blue','Cyan'),
('Bill','Cyan','Blue'),
('Sara','Blue','Blue');

insert table2 (name,hand,foot) values
('Carl','Left','Right'),
('Sara','Right','Left');

查询

Select Name, Eyes, Hair, Null as Hand, Null as Foot from table1
where not exists (select * from table2 where table2.name=table1.name) 
union 
Select Name, Null as Eyes, Null as Hair, Hand, Foot from table2
where not exists (select * from table1 where table1.name=table2.name) 
union 
select t1.Name,t1.Eyes,t1.Hair,t2.Hand,t2.Foot 
from table1 t1 
join table2 t2 
on t2.Name=t1.Name;

结果

+------+------+------+-------+-------+
| Name | Eyes | Hair | Hand  | Foot  |
+------+------+------+-------+-------+
| Able | Blue | Cyan | NULL  | NULL  |
| Bill | Cyan | Blue | NULL  | NULL  |
| Carl | NULL | NULL | Left  | Right |
| Sara | Blue | Blue | Right | Left  |
+------+------+------+-------+-------+
4 rows in set (0.00 sec)

我所做的查询有3个部分。第一个是表1中不在表2中。第二个反之亦然。第三部分是共同的(加入)。对于连接,t1和t2表示表名的简单别名。

对于联合的前两部分,我使用not exists子句而不是NOT IN子句,因为后者是我从未使用的东西,因为过度偏执危险的NOT IN结果。如果一个人不能很好地了解他们的数据,那么NOT IN可能会返回意外结果,并在数据可空性的情况下浪费大量时间进行调试。

答案 3 :(得分:-1)

SELECT FROM table1
FULL OUTER JOIN table2 
ON table1.name = table2.name
WHERE table1.name = null
OR table2.name = null