【问题标题】:Table Comparison with NULL value与 NULL 值的表比较
【发布时间】:2016-01-14 23:22:38
【问题描述】:

我正在寻找比较两个表并返回包含两个表之间差异的行的最佳方法。

//表A

CREATE TABLE `mydb`.`a` (
  `id` int(10) unsigned NOT NULL,
  `color` varchar(45) DEFAULT NULL,
  `animal` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `mydb`.`a` 
    (id,color,animal) 
VALUES 
    (1,"red",""),
    (2,"blue","cat"),
    (3,"green","dog");
    (4,"orange","fish");

//表B

CREATE TABLE `mydb`.`b` (
  `id` int(10) unsigned NOT NULL,
  `color` varchar(45) DEFAULT NULL,
  `animal` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `mydb`.`b` 
    (id,color,animal) 
VALUES 
    (1,"red",""),
    (2,"blue","cat"),
    (3,"green","bird");
    (4,"brown","fish");

该语句将返回表 B 的第 3,4 行,因为 birdbrowndogorange 不同。

【问题讨论】:

  • AND IS NOT NULL ??
  • @Dagon 我应该在哪里插入?
  • 你想达到什么输出?
  • @GordonLinoff 来生成差异,所以如果用户在 xls 上更改了某些内容然后加载它,它会转到表 facilities_update 然后运行上面的语句,现在发生的事情是即使它们在facilities 表和facilities_update 中是一个空值(空白),即使它们没有不同,它们也都是空值。
  • @GordonLinoff 所以现在我对 xls 做了 4 处更改,所以它应该只提取这 4 行,但结果中包含任何具有空值的行

标签: php mysql sql database compare


【解决方案1】:

NULL 表示缺少信息。它永远不会匹配其他值(包括其他 NULL)。因此,例如,虽然零等于零:

SQL> select case when 0 = 0 then 'true' else 'false' end ;
case when 0 = 0 then 'true' else 'false' end
--------------------------------------------
true                                    

NULL 等于 NULL:

SQL> select case when null = null then 'true' else 'false' end ;
case when null = null then 'true' else 'false' end
--------------------------------------------------
false                             

如果你想匹配它们,你必须将它们转换 NULL 到其他值(例如零):

SQL> select case when ifnull(null, 0) = ifnull(null, 0) then 'true' else 'false' end ;
case when ifnull(null, 0) = ifnull(null, 0) then 'true' else 'false' end
------------------------------------------------------------------------
true   

编辑

假设你有:

mysql> select * from a;
+----+--------+--------+
| id | color  | animal |
+----+--------+--------+
|  1 | red    |        |
|  2 | blue   | cat    |
|  3 | green  | dog    |
|  4 | orange | fish   |
+----+--------+--------+
4 rows in set (0.00 sec)

mysql> select * from b;
+----+-------+--------+
| id | color | animal |
+----+-------+--------+
|  1 | red   |        |
|  2 | blue  | cat    |
|  3 | green | bird   |
|  4 | brown | fish   |
+----+-------+--------+
4 rows in set (0.00 sec)

我会使用:

mysql> select b.* from b left outer join a on a.id = b.id and 
       a.animal = b.animal and a.color = b.color 
       where a.id is null and a.animal is null and a.color is null ;
+----+-------+--------+
| id | color | animal |
+----+-------+--------+
|  3 | green | bird   |
|  4 | brown | fish   |
+----+-------+--------+
2 rows in set (0.00 sec)

查找 B 中与 A 中对应行不同的行。 并且:

mysql> select a.* from a left outer join b on a.id = b.id and 
       a.animal = b.animal and a.color = b.color 
       where b.id is null and b.animal is null and b.color is null ;
+----+--------+--------+
| id | color  | animal |
+----+--------+--------+
|  3 | green  | dog    |
|  4 | orange | fish   |
+----+--------+--------+
2 rows in set (0.00 sec)

在 A 中查找与 B 中相应行不同的行。

【讨论】:

  • 或者,更好的是,ISNULL(a) AND ISNULL(b)
  • 我不想匹配它们,我不想取消匹配它们......我的意思是两个表都包含该列/行的空白单元格,但它说他们值是不同的......即使它们都是空白/空的。我只想要差异。
  • @JordanDavis:是的,mauro 解释了这一点。 “空白/空”是指NULL,而NULL 不是一个值。这是缺乏价值。平等是价值观之间的比较。一个NULL等于 另一个NULL,所以这完全是预期的行为。 mauro 进一步提出了实现实际目标的替代方法,我也是。
  • @mauro 所以你说运行语句之前将两个表中的所有空值转换为 (0's|NULL|false) 使其具有实际值然后运行语句?
  • @JordanDavis 您可以更改基表以将 NULL 替换为其他值(假设您可以...)或在运行 SELECT 时提取 NULL 并在飞行中“替换”它们(ifnull() 或,更好,是 LightnessRacesinOrbit 建议的 isnull() 。重要的是您要了解 NULL 表示 unknownunknown not 等于 unknown
猜你喜欢
  • 2011-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-01
  • 1970-01-01
  • 2012-07-24
  • 1970-01-01
相关资源
最近更新 更多