如何连接2个表并匹配空值

时间:2014-05-31 02:28:58

标签: mysql sql

我有这些表格:

mysql> select bookId, productId, clusterId, symbolId, shares from SymbolAimOrderStats where bookId = "BFM";
+--------+-----------+-----------+----------+--------+
| bookId | productId | clusterId | symbolId | shares |
+--------+-----------+-----------+----------+--------+
| BFM    | NULL      | NULL      | NULL     |    522 |
| BFM    | BFM       | NULL      | NULL     |    522 | 
| BFM    | BFM       | BFM       | NULL     |    522 | 
| BFM    | BFM       | BFM       | 0000f52a |    506 | 
| BFM    | BFM       | BFM       | 00010a4d |      2 | 
| BFM    | BFM       | BFM       | 00010a7c |      1 | 
| BFM    | BFM       | BFM       | 00010a89 |      3 | 
| BFM    | BFM       | BFM       | 00010ba3 |      3 | 
| BFM    | BFM       | BFM       | 00013c7e |      3 | 
| BFM    | BFM       | BFM       | 00013c97 |      4 | 
+--------+-----------+-----------+----------+--------+
10 rows in set (0.00 sec)

mysql> select bookId, productId, clusterId, symbolId, shares from SymbolOrderStats where bookId = "BFM";
+--------+-----------+-----------+----------+--------+
| bookId | productId | clusterId | symbolId | shares |
+--------+-----------+-----------+----------+--------+
| BFM    | NULL      | NULL      | NULL     |    393 | 
| BFM    | BFM       | NULL      | NULL     |    393 | 
| BFM    | BFM       | BFM       | NULL     |    393 | 
| BFM    | BFM       | BFM       | 0000f52a |    377 | 
| BFM    | BFM       | BFM       | 00010a4d |      2 | 
| BFM    | BFM       | BFM       | 00010a7c |      1 | 
| BFM    | BFM       | BFM       | 00010a89 |      3 | 
| BFM    | BFM       | BFM       | 00010ba3 |      3 | 
| BFM    | BFM       | BFM       | 00013c7e |      3 | 
| BFM    | BFM       | BFM       | 00013c97 |      4 | 
+--------+-----------+-----------+----------+--------+
10 rows in set (0.00 sec)

我想加入这些表并从两者中获取shares列,包括具有NULL的行。

我知道你不能匹配NULL,所以这当然不能给我我想要的结果:

mysql> select a.bookId, a.productId, a.clusterId, a.symbolId, a.shares, o.shares 
from SymbolAimOrderStats a 
left join SymbolOrderStats o 
on a.bookId = o.bookId and a.productId = o.productId and 
a.clusterId = o.clusterId and a.symbolId = o.symbolId where a.bookId = "BFM";

所以我试过这个:

mysql> select a.bookId, a.productId, a.clusterId, a.symbolId, a.shares, o.shares 
from SymbolAimOrderStats a 
left join SymbolOrderStats o 
on a.bookId = o.bookId and 
(a.productId = o.productId or (a.productId is null and o.productId is null)) and 
(a.clusterId = o.clusterId or (a.clusterId is null and o.clusterId is null)) and
(a.symbolId = o.symbolId or (a.symbolId is null or a.symbolId is null)) 
where a.bookId = "BFM";

但这也没有给出我想要的东西。有人可以告诉我如何获得我想要的结果集吗?

这是我要回复的内容:

+--------+-----------+-----------+----------+--------+--------+
| bookId | productId | clusterId | symbolId | shares | shares |
+--------+-----------+-----------+----------+--------+--------+
| BFM    | NULL      | NULL      | NULL     |    522 |    393 |
| BFM    | BFM       | NULL      | NULL     |    522 |    393 | 
| BFM    | BFM       | BFM       | NULL     |    522 |    393 | 
| BFM    | BFM       | BFM       | 0000f52a |    506 |    377 | 
| BFM    | BFM       | BFM       | 00010a4d |      2 |      2 | 
| BFM    | BFM       | BFM       | 00010a7c |      1 |      1 | 
| BFM    | BFM       | BFM       | 00010a89 |      3 |      3 | 
| BFM    | BFM       | BFM       | 00010ba3 |      3 |      3 | 
| BFM    | BFM       | BFM       | 00013c7e |      3 |      3 | 
| BFM    | BFM       | BFM       | 00013c97 |      4 |      4 | 
+--------+-----------+-----------+----------+--------+--------+
10 rows in set (0.00 sec)

这是在MySQL。

2 个答案:

答案 0 :(得分:1)

NULL值的最后一个条件可能使用and代替or

select a.bookId, a.productId, a.clusterId, a.symbolId, a.shares, o.shares 
from SymbolAimOrderStats a 
left join SymbolOrderStats o 
on a.bookId = o.bookId and 
(a.productId = o.productId or (a.productId is null and o.productId is null)) and 
(a.clusterId = o.clusterId or (a.clusterId is null and o.clusterId is null)) and
(a.symbolId = o.symbolId or (a.symbolId is null and o.symbolId is null)) 
------------------------------------------------^ --^
where a.bookId = "BFM";

答案 1 :(得分:0)

如果您需要NULL有意义,请将其更改为有意义的内容。

select  a.bookId, a.productId, a.clusterId, a.symbolId, a.shares, o.shares 
from    SymbolAimOrderStats a 
left join SymbolOrderStats o 
  on    a.bookId = o.bookId
   and ifnull( a.productId, @dummy ) = ifnull( o.productId, @dummy )
   and ifnull( a.clusterId, @dummy ) = ifnull( o.clusterId, @dummy )
   and ifnull( a.symbolId, @dummy ) = ifnull( o.symbolId, @dummy ) 
where a.bookId = "BFM";

@dummy只要与非空值不冲突就可以消除将NULL与非NULL匹配的可能性,并且是相同的数据键入字段。如果productId,clusterId和symbolId是不同的类型,则需要三个虚拟变量。或者您可以在那里对值进行硬编码,但这不是一个好习惯。

然而,这提出了一个问题,即如果表中的NULL值实际意味着某些东西,为什么它们不已设置为这些值?我并不是说要批评 - 可能有完全合理的理由他们必须保持NULL。但也许你可能会忽略改善数据的机会。