MySQL - 查找孤立行

3

我有两个MySQL表(testa,resa),如下所示:

       CREATE TABLE RESA (
       `tdate` date,
       `reg` varchar(4), 
       `num` int(2), 
       `P1`  int(2), 
       `P2`  int(2),    
       `P3`  int(2), 
       `P4`  int(2)   
       ); 

       CREATE TABLE TESTA (
       `tdate` date,
       `reg` varchar(4), 
       `numa` int(2), 
       `numb` int(2),
       `name` varchar(10),
       `reso` varchar(2)
       );

       INSERT INTO RESA VALUES 
       ("2015-12-06", 'NERA', 2, 1,2,3,4),
       ("2015-12-06", 'WAS', 5, 5,6,7,9),
       ("2015-12-08", 'NERA', 1, 3,5,6,8);

      INSERT INTO TESTA VALUES 
      ("2015-12-06", 'NERA', 2,1, 'Qalyub',""),
      ("2015-12-06", 'NERA', 2,2, 'Kunjin',""),
      ("2015-12-06", 'NERA', 2,3, 'Carrizal',""),
      ("2015-12-07", 'NERA', 2,4, 'Amur',""),
      ("2015-12-06", 'NERA', 2,6, 'Heni',""),
      ("2015-12-06", 'NERA', 2,7, 'El Moro',""),
      ("2015-12-07", 'NERA', 2,10, 'Fifth-C',""),
      ("2015-12-06", 'WAS', 5,2, 'Bora',""),
      ("2015-12-06", 'WAS', 5,3, 'Imjin',""),
      ("2015-12-06", 'WAS', 5,5, 'RR',""),
      ("2015-12-07", 'WAS', 5,6, 'Qalyub',""),
      ("2015-12-06", 'WAS', 5,7, 'RR',""),
      ("2015-12-07", 'WAS', 5,9, 'Qalyub',""),
      ("2015-12-07", 'NERA', 1,2, 'Kunjin',""),
      ("2015-12-07", 'NERA', 1,3, 'Carrizal',""),
      ("2015-12-07", 'NERA', 1,5, 'Amur',""),
      ("2015-12-07", 'NERA', 1,6, 'Bora',""),
      ("2015-12-07", 'NERA', 1,7, 'Imjin',""),
      ("2015-12-07", 'NERA', 1,8, 'Magboy',"") ;  

实际的表格有数千行,以及其他列。

对于每个RESA行,都有一个可变数量的关联TESTA行,其中每个表的前3个字段(日期、reg、num/date、reg、numa)建立了关系。行在两个表中是不同的,即没有重复。

每个实验结果(RESA)行至少有2个测试(TESTA)行。

当每个表的前3个字段匹配时,将会在一个TESTA行中为RESA.p1和TESTA.numB找到匹配项,因此以下内容将返回两个表格中的所有相关行,这些行将用于更新TESTA中的其他列:

SELECT * FROM TESTA as T
  NATURAL JOIN RESA AS R
  WHERE T.numb = R.p1;

因此,要更新的TESTA行数应与RESA表中的行数相匹配,即下面的计数将相同:

mysql>SELECT count(*) FROM TESTA as T
           NATURAL JOIN RESA AS R
           WHERE T.numb = R.p1;



mysql>SELECT COUNT(*) FROM RESA;  

在示例数据中,它们不相同,这是我试图确定的问题。在小样本中,罪魁祸首很容易找到: 最后一行RESA.tdate:("2015-12-08", 'NERA', 1, 3,5,6,8); 不正确,应该与TESTA中相关数据匹配为"2015-12-07"。
我的问题是如何在更大的数据库中识别RESA中的孤儿,即那些没有在TESTA中具有相关数据的行?
以上的反义词:
SELECT count(*) FROM TESTA as T
           NATURAL JOIN RESA AS R
           WHERE T.numb != R.p1;

由于RESA具有唯一的tdate值(即在TESTA中不存在且不正确),相关字段没有自然连接,因此无法工作。

我的实际数据库有数千行,存在2处差异,是否有脚本可以用来识别它们?


看看我的博客文章,其中有几个查找孤立行的选项:http://mechanics.flite.com/blog/2016/02/05/finding-and-deleting-orphaned-rows-in-mysql/ - Ike Walker
谢谢Ike,你说得很到位。 - Mr Ed
1个回答

11
那么就像 LEFT JOIN 这样的东西吗?
SELECT t.* FROM RESA t
LEFT OUTER JOIN TESTA s
 ON(t.tdate = s.tdate AND t.reg = s.reg and t.num = s.numa)
WHERE s.tdate is null

或者使用NOT EXISTS()
SELECT t.* FROM RESA t
WHERE NOT EXISTS(SELECT 1 FROM TESTA s
                 WHERE t.tdate = s.tdate
                   AND t.reg = s.reg 
                   AND t.num = s.numa)

1
谢谢您的快速回复,两种解决方案都非常有效。 - Mr Ed
1
我知道这是在2016年的事情了,但我刚刚发现了你的解决方案,它们简单而完美!谢谢! - GaryC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接