mysql JOIN - 左,右还是外?

时间:2011-10-16 14:25:08

标签: mysql

我有2个表,其中包含以下列: 表1

+--------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| symbol | varchar(45) | NO | MUL | NULL | |
| v_dt | date | NO | | NULL | |
| e_dt | date | NO | | NULL | |
| col_s | decimal(10,4) | NO | | NULL | |
| col_o | decimal(10,4) | NO | | NULL | |
| col_b | decimal(10,4) | NO | | NULL | |
| col_a | decimal(10,4) | NO | | NULL | |
| col_l | decimal(10,4) | NO | | NULL | |
| col_v | bigint(20) | NO | | NULL | |
| col_t | enum('a','b') | NO | | NULL | |
+--------------+---------------+------+-----+---------+----------------+

和表2:

+------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+-------+
| t_date | date | NO | PRI | NULL | |
| e_date | date | NO | | NULL | |
| symbol | varchar(45) | NO | PRI | NULL | |
| col_i | decimal(10,6) | NO | | NULL | |
| col_b | decimal(10,6) | NO | | NULL | |
| col_d | decimal(10,6) | NO | | NULL | |
| col_g | decimal(10,6) | NO | | NULL | |
| col_v | decimal(10,6) | NO | | NULL | |
| col_t | decimal(10,6) | NO | | NULL | |
| col_r | decimal(10,6) | NO | | NULL | |
+------------+---------------+------+-----+---------+-------+

我想检索table1.col_b,table1.col_a和table2.col_d 所以,我写了以下

SELECT col_b, col_a, col_d FROM table1 LEFT JOIN table2 ON table1.symbol=table2.symbol;

但它没有返回它应该拥有的40行,而是继续运行以检索具有不相关数据的4000行,所以我猜我已经错误地写了JOIN。 你能来吗?让我知道写这个来检索所需数据的正确方法是什么。谢谢! INNER JOIN的结果(我更改了查询以包含日期,因此结果更有意义,我希望)

SELECT v_dt, e_dt, col_d FROM table1 INNER JOIN table2 ON table1.symbol=table2.symbol;

| 2011-09-26   | 2011-11-18 |   2.030130 |
| 2011-09-27   | 2011-11-18 |   2.030130 |
| 2011-09-28   | 2011-11-18 |   2.030130 |
| 2011-09-29   | 2011-11-18 |   2.030130 |
| 2011-09-30   | 2011-11-18 |   2.030130 |
| 2011-10-03   | 2011-11-18 |   2.030130 |
| 2011-10-04   | 2011-11-18 |   2.030130 |
| 2011-10-05   | 2011-11-18 |   2.030130 |
| 2011-10-06   | 2011-11-18 |   2.030130 |
| 2011-10-07   | 2011-11-18 |   2.030130 |
| 2011-10-10   | 2011-11-18 |   2.030130 |
| 2011-10-11   | 2011-11-18 |   2.030130 |
| 2011-10-12   | 2011-11-18 |   2.030130 |
| 2011-10-13   | 2011-11-18 |   2.030130 |
| 2011-10-14   | 2011-11-18 |   2.030130 |
| 2011-08-09   | 2011-11-18 |   1.628250 |
| 2011-08-10   | 2011-11-18 |   1.628250 |
| 2011-08-11   | 2011-11-18 |   1.628250 |
| 2011-08-12   | 2011-11-18 |   1.628250 |
| 2011-08-15   | 2011-11-18 |   1.628250 |
| 2011-08-16   | 2011-11-18 |   1.628250 |
| 2011-08-17   | 2011-11-18 |   1.628250 |
| 2011-08-18   | 2011-11-18 |   1.628250 |
| 2011-08-19   | 2011-11-18 |   1.628250 |
| 2011-08-22   | 2011-11-18 |   1.628250 |
| 2011-08-24   | 2011-11-18 |   1.628250 |
| 2011-08-25   | 2011-11-18 |   1.628250 |
| 2011-08-26   | 2011-11-18 |   1.628250 |
| 2011-08-29   | 2011-11-18 |   1.628250 |
| 2011-08-30   | 2011-11-18 |   1.628250 |
| 2011-08-31   | 2011-11-18 |   1.628250 |
| 2011-09-01   | 2011-11-18 |   1.628250 |
| 2011-09-02   | 2011-11-18 |   1.628250 |
| 2011-09-06   | 2011-11-18 |   1.628250 |
| 2011-09-07   | 2011-11-18 |   1.628250 |
| 2011-09-08   | 2011-11-18 |   1.628250 |
| 2011-09-09   | 2011-11-18 |   1.628250 |
| 2011-09-13   | 2011-11-18 |   1.628250 |
| 2011-09-14   | 2011-11-18 |   1.628250 |
| 2011-09-15   | 2011-11-18 |   1.628250 |
| 2011-09-16   | 2011-11-18 |   1.628250 |
| 2011-09-19   | 2011-11-18 |   1.628250 |
| 2011-09-20   | 2011-11-18 |   1.628250 |
| 2011-09-21   | 2011-11-18 |   1.628250 |
| 2011-09-22   | 2011-11-18 |   1.628250 |
| 2011-09-23   | 2011-11-18 |   1.628250 |
| 2011-09-26   | 2011-11-18 |   1.628250 |
| 2011-09-27   | 2011-11-18 |   1.628250 |
| 2011-09-28   | 2011-11-18 |   1.628250 |
| 2011-09-29   | 2011-11-18 |   1.628250 |
| 2011-09-30   | 2011-11-18 |   1.628250 |
| 2011-10-03   | 2011-11-18 |   1.628250 |
| 2011-10-04   | 2011-11-18 |   1.628250 |
| 2011-10-05   | 2011-11-18 |   1.628250 |
| 2011-10-06   | 2011-11-18 |   1.628250 |
| 2011-10-07   | 2011-11-18 |   1.628250 |
| 2011-10-10   | 2011-11-18 |   1.628250 |
| 2011-10-11   | 2011-11-18 |   1.628250 |
| 2011-10-12   | 2011-11-18 |   1.628250 |
| 2011-10-13   | 2011-11-18 |   1.628250 |
| 2011-10-14   | 2011-11-18 |   1.628250 |
| 2011-08-09   | 2011-11-18 |   1.254390 |
| 2011-08-10   | 2011-11-18 |   1.254390 |
| 2011-08-11   | 2011-11-18 |   1.254390 |
| 2011-08-12   | 2011-11-18 |   1.254390 |
| 2011-08-15   | 2011-11-18 |   1.254390 |
| 2011-08-16   | 2011-11-18 |   1.254390 |
| 2011-08-17   | 2011-11-18 |   1.254390 |
| 2011-08-18   | 2011-11-18 |   1.254390 |
| 2011-08-19   | 2011-11-18 |   1.254390 |
| 2011-08-22   | 2011-11-18 |   1.254390 |
| 2011-08-24   | 2011-11-18 |   1.254390 |
| 2011-08-25   | 2011-11-18 |   1.254390 |
| 2011-08-26   | 2011-11-18 |   1.254390 |
| 2011-08-29   | 2011-11-18 |   1.254390 |
| 2011-08-30   | 2011-11-18 |   1.254390 |
| 2011-08-31   | 2011-11-18 |   1.254390 |
| 2011-09-01   | 2011-11-18 |   1.254390 |
| 2011-09-02   | 2011-11-18 |   1.254390 |
| 2011-09-06   | 2011-11-18 |   1.254390 |
| 2011-09-07   | 2011-11-18 |   1.254390 |
| 2011-09-08   | 2011-11-18 |   1.254390 |
| 2011-09-09   | 2011-11-18 |   1.254390 |
| 2011-09-13   | 2011-11-18 |   1.254390 |
| 2011-09-14   | 2011-11-18 |   1.254390 |
| 2011-09-15   | 2011-11-18 |   1.254390 |
| 2011-09-16   | 2011-11-18 |   1.254390 |
| 2011-09-19   | 2011-11-18 |   1.254390 |
| 2011-09-20   | 2011-11-18 |   1.254390 |
| 2011-09-21   | 2011-11-18 |   1.254390 |
| 2011-09-22   | 2011-11-18 |   1.254390 |
| 2011-09-23   | 2011-11-18 |   1.254390 |
| 2011-09-26   | 2011-11-18 |   1.254390 |
| 2011-09-27   | 2011-11-18 |   1.254390 |
| 2011-09-28   | 2011-11-18 |   1.254390 |
| 2011-09-29   | 2011-11-18 |   1.254390 |
| 2011-09-30   | 2011-11-18 |   1.254390 |
| 2011-10-03   | 2011-11-18 |   1.254390 |
| 2011-10-04   | 2011-11-18 |   1.254390 |
| 2011-10-05   | 2011-11-18 |   1.254390 |
| 2011-10-06   | 2011-11-18 |   1.254390 |
| 2011-10-07   | 2011-11-18 |   1.254390 |
| 2011-10-10   | 2011-11-18 |   1.254390 |
| 2011-10-11   | 2011-11-18 |   1.254390 |
| 2011-10-12   | 2011-11-18 |   1.254390 |
| 2011-10-13   | 2011-11-18 |   1.254390 |
| 2011-10-14   | 2011-11-18 |   1.254390 |
| 2011-08-09   | 2011-11-18 |   1.019710 |
| 2011-08-10   | 2011-11-18 |   1.019710 |
| 2011-08-11   | 2011-11-18 |   1.019710 |
| 2011-08-12   | 2011-11-18 |   1.019710 |
| 2011-08-15   | 2011-11-18 |   1.019710 |
| 2011-08-16   | 2011-11-18 |   1.019710 |
| 2011-08-17   | 2011-11-18 |   1.019710 |
| 2011-08-18   | 2011-11-18 |   1.019710 |
| 2011-08-19   | 2011-11-18 |   1.019710 |

我希望获得的是表1中的以下2列,第3列是表2中的col_d。因此我期待45行。

+--------------+------------+
| 2011-08-09   | 2013-01-18 |
| 2011-08-10   | 2013-01-18 |
| 2011-08-11   | 2013-01-18 |
| 2011-08-12   | 2013-01-18 |
| 2011-08-15   | 2013-01-18 |
| 2011-08-16   | 2013-01-18 |
| 2011-08-17   | 2013-01-18 |
| 2011-08-18   | 2013-01-18 |
| 2011-08-19   | 2013-01-18 |
| 2011-08-22   | 2013-01-18 |
| 2011-08-24   | 2013-01-18 |
| 2011-08-25   | 2013-01-18 |
| 2011-08-26   | 2013-01-18 |
| 2011-08-29   | 2013-01-18 |
| 2011-08-30   | 2013-01-18 |
| 2011-08-31   | 2013-01-18 |
| 2011-09-01   | 2013-01-18 |
| 2011-09-02   | 2013-01-18 |
| 2011-09-06   | 2013-01-18 |
| 2011-09-07   | 2013-01-18 |
| 2011-09-08   | 2013-01-18 |
| 2011-09-09   | 2013-01-18 |
| 2011-09-13   | 2013-01-18 |
| 2011-09-14   | 2013-01-18 |
| 2011-09-15   | 2013-01-18 |
| 2011-09-16   | 2013-01-18 |
| 2011-09-20   | 2013-01-18 |
| 2011-09-21   | 2013-01-18 |
| 2011-09-22   | 2013-01-18 |
| 2011-09-23   | 2013-01-18 |
| 2011-09-26   | 2013-01-18 |
| 2011-09-27   | 2013-01-18 |
| 2011-09-28   | 2013-01-18 |
| 2011-09-29   | 2013-01-18 |
| 2011-09-30   | 2013-01-18 |
| 2011-10-03   | 2013-01-18 |
| 2011-10-04   | 2013-01-18 |
| 2011-10-05   | 2013-01-18 |
| 2011-10-06   | 2013-01-18 |
| 2011-10-07   | 2013-01-18 |
| 2011-10-10   | 2013-01-18 |
| 2011-10-11   | 2013-01-18 |
| 2011-10-12   | 2013-01-18 |
| 2011-10-13   | 2013-01-18 |
| 2011-10-14   | 2013-01-18 |
+--------------+------------+
45 rows in set (0.02 sec)

添加GROUP BY v_dt,e_dt将其降低到45行,table1的列是正确的。唯一的问题是它现在显示table2.col_d的相同值(5.530000),它不是它应该是: - (

+--------------+------------+----------+
| 2011-08-09   | 2013-01-18 | 5.530000 |
| 2011-08-10   | 2013-01-18 | 5.530000 |
| 2011-08-11   | 2013-01-18 | 5.530000 |
| 2011-08-12   | 2013-01-18 | 5.530000 |
| 2011-08-15   | 2013-01-18 | 5.530000 |
| 2011-08-16   | 2013-01-18 | 5.530000 |
| 2011-08-17   | 2013-01-18 | 5.530000 |
| 2011-08-18   | 2013-01-18 | 5.530000 |
| 2011-08-19   | 2013-01-18 | 5.530000 |
| 2011-08-22   | 2013-01-18 | 5.530000 |
| 2011-08-24   | 2013-01-18 | 5.530000 |
| 2011-08-25   | 2013-01-18 | 5.530000 |
| 2011-08-26   | 2013-01-18 | 5.530000 |
| 2011-08-29   | 2013-01-18 | 5.530000 |
| 2011-08-30   | 2013-01-18 | 5.530000 |
| 2011-08-31   | 2013-01-18 | 5.530000 |
| 2011-09-01   | 2013-01-18 | 5.530000 |
| 2011-09-02   | 2013-01-18 | 5.530000 |
| 2011-09-06   | 2013-01-18 | 5.530000 |
| 2011-09-07   | 2013-01-18 | 5.530000 |
| 2011-09-08   | 2013-01-18 | 5.530000 |
| 2011-09-09   | 2013-01-18 | 5.530000 |
| 2011-09-13   | 2013-01-18 | 5.530000 |
| 2011-09-14   | 2013-01-18 | 5.530000 |
| 2011-09-15   | 2013-01-18 | 5.530000 |
| 2011-09-16   | 2013-01-18 | 5.530000 |
| 2011-09-20   | 2013-01-18 | 5.530000 |
| 2011-09-21   | 2013-01-18 | 5.530000 |
| 2011-09-22   | 2013-01-18 | 5.530000 |
| 2011-09-23   | 2013-01-18 | 5.530000 |
| 2011-09-26   | 2013-01-18 | 5.530000 |
| 2011-09-27   | 2013-01-18 | 5.530000 |
| 2011-09-28   | 2013-01-18 | 5.530000 |
| 2011-09-29   | 2013-01-18 | 5.530000 |
| 2011-09-30   | 2013-01-18 | 5.530000 |
| 2011-10-03   | 2013-01-18 | 5.530000 |
| 2011-10-04   | 2013-01-18 | 5.530000 |
| 2011-10-05   | 2013-01-18 | 5.530000 |
| 2011-10-06   | 2013-01-18 | 5.530000 |
| 2011-10-07   | 2013-01-18 | 5.530000 |
| 2011-10-10   | 2013-01-18 | 5.530000 |
| 2011-10-11   | 2013-01-18 | 5.530000 |
| 2011-10-12   | 2013-01-18 | 5.530000 |
| 2011-10-13   | 2013-01-18 | 5.530000 |
| 2011-10-14   | 2013-01-18 | 5.530000 |
+--------------+------------+----------+

这是更新的查询。 select table1.v_dt, table1.e_dt, table2.col_b from table1 inner join table2 on table1.symbol=table2.symbol group by v_dt, e_dt; 为了进一步缩小结果,我也跑了 select table1.v_dt, table1.e_dt, table2.col_b from table1 inner join table2 on table1.symbol='P00055000' group by v_dt, e_dt; 但我仍然得到相同的结果,然后

select symbol, count(*) from table2 where symbol='P00055000' group by symbol;

+--------------------+----------+
| P00055000 |       40 |
+--------------------+----------+
1 row in set (0.02 sec)

2 个答案:

答案 0 :(得分:2)

如果你有两张表A和B:

  • LEFT JOIN B =选择B中与连接条件匹配的所有行A和任何行,如果B与连接条件不匹配,则选择NULL
  • 正确加入B =选择所有行B和A中与连接条件匹配的所有行,如果A与连接条件不匹配,则选择NULL
  • INNER JOIN B =仅选择A和B中与连接条件匹配的行

对于在连接表上的LEFT / RIGHT连接中选择的任何列,如果该行与连接条件不匹配,则将出现NULL值。


例如说我们有两个表

Table A (id, name, description)
Table B (id, a_id, group_id, date)

当我们在下面运行 LEFT JOIN 时,如果找不到B表中的记录,我们预计查询的结果将为B.group_id和B.date返回NULL。

SELECT A.id, A.name, A.description, B.group_id, B.date FROM A
LEFT JOIN B ON B.a_id=A.id

导致

id | name | description | group_id | date
1  | Test | Test        | 2        | 2011-3-4
2  | Test | Test        | NULL     | NULL

如您所见,第一行成功地在A和B中找到了与连接条件匹配的记录。另一方面,第2行无法在B中找到匹配的记录,因此它添加了NULL值。


让我们看一下 RIGHT JOIN 。这实际上是LEFT JOIN的反转。我们希望B中的所有记录都包含他们的数据,但如果A中的记录不匹配,它将包含NULLS。

SELECT A.id, A.name, A.description, B.group_id, B.date FROM A
RIGHT JOIN B ON B.a_id=A.id

导致

id   | name | description | group_id | date
1    | Test | Test        | 2        | 2011-3-4
NULL | NULL | NULL        | 3        | 2011-5-6

正如您所看到的那样,第一行成功地在A和B中找到了与连接条件匹配的记录(与LEFT JOIN相同)。另一方面,第2行无法在A中找到匹配的记录,因此它添加了NULL值。


最后让我们看一下 INNER JOIN 。 INNER JOIN通常是最有用的连接,因为它只返回A和B中匹配的记录,这通常是您正在寻找的记录

SELECT A.id, A.name, A.description, B.group_id, B.date FROM A
INNER JOIN B ON B.a_id=A.id

导致

id   | name | description | group_id | date
1    | Test | Test        | 2        | 2011-3-4

现在我们只返回A和B中匹配的记录,并忽略所有其余记录。希望这能为你解决问题。

答案 1 :(得分:1)

我认为你正在寻找inner join。左连接返回table1中的所有记录以及匹配的table2值,如果没有匹配的table2,则返回null。

内部联接从两个集合中返回每个匹配对(基于您的连接条件),但不返回任何没有匹配的记录。

http://en.wikipedia.org/wiki/Join_(SQL)

你获得这么多记录的原因是因为连接返回了两个表的笛卡尔积。例如,如果您有一个包含10条记录的表和另一条包含20条记录的表,则最终会有200条记录。这显然是无用的,因此您添加连接条件仅返回逻辑上一起记录的记录,通常基于外键关系。所以,对于:

Table1 - Table1Key, Table1Value
Table2 - Table2Key, Table1KeyReference, Table2Value

and the values

Table1
1,'1'
2,'2'
3,'3'
4,'4'
5,'5'

Table2
1,1,'1-1'
2,1,'1-2'
3,2,'2-3'

使用该数据,以下语句

select *
    from Table1
        inner join Table2

返回

Table1Key,Table1Value,Table2Key,Table1KeyReference, Table2Value
1,'1',1,1,'1-1'
1,'1',2,1,'1-2'
1,'1',3,2,'2-3'
2,'2',1,1,'1-1'
2,'2',2,1,'1-2'
2,'2',3,2,'2-3'
....

等。从这15种组合中,只有“正确”,所以我们需要添加一个连接条件:

select *
    from Table1
        inner join Table2 on(Table1.Table1Key=Table2.Table1KeyReference)

返回:

1,'1',1,1,'1-1'
1,'1',2,1,'1-2'
2,'2',3,2,'2-3'

这只返回表2中的3的原因是Table2中的每一行对应于表1中的每一行而只有一行。

您的案例中的问题是您没有定义两个表之间的关系。如果您的第二个表格中有40个P00055000符号,并且您的第一个符号中有2个符号,那么您将从您的加入获得80个结果。如果有40个不同的符号,每个符号在第二个表中另外有40行,在第一个表中有2个,那么你最终会有3200行等等。很多这可能是毫无意义的数据,这是因为你没有强烈定义两个表之间的关系。

所以,所有人都说,当你选择时,你想要什么结果?对于Table1中的给定行,如果您使用表2中的每一行加入它,您想要返回哪些行?从那里,你应该能够制作正确的连接条件。如果这两行紧密相关(父子等),您应该考虑重新分解表以加入主/外键关系并删除重复数据。

顺便说一句,我假设这些不是你真正的表和字段名称。如果是,请将它们更改为有意义的内容。列名称的长度不会影响查询性能,但可以更轻松地共享,讨论和修改代码。