我有两个表:AP
和表AP supervisory visits
,分别有一对多关系。 AP supervisory visits
没有主键或唯一索引(因此可能有点难以使用)和函数" IN()"这是不容易的。
表AP
:
+------------------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------------------+-------------+------+-----+---------+-------+
| HID | varchar(50) | NO | PRI | NULL | |
| yr | varchar(50) | NO | PRI | NULL | |
| mo | varchar(50) | NO | PRI | NULL | |
表AP supervisory visits
:
+------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+-------------+------+-----+---------+-------+
| HID | varchar(50) | YES | MUL | NULL | |
| yr | varchar(50) | YES | | NULL | |
| mo | varchar(50) | YES | | NULL | |
| exported | datetime | YES | | NULL | |
| visitor name | varchar(50) | YES | | NULL | |
| title | varchar(50) | YES | | NULL | |
| reason for visit | varchar(50) | YES | | NULL | |
| number of visits | int(11) | YES | MUL | 0 | |
+------------------+-------------+------+-----+---------+-------+
我在AP中有大约8000条记录,在AP supervisory visits
中有1700条唯一记录(使用HID,年,月)。我希望AP
表中没有'孩子的所有记录'在AP supervisory visits
表中。使用关于Stakeoverflow的其他文章我得出结论我应该使用" NOT IN()" 。这适用于我的几个具有相似关系的表,但不是这次(注意最后一个查询是反向的,它缺少NOT):
mysql> SELECT HID, yr, mo FROM AP
-> WHERE (HID, yr, mo) NOT IN(SELECT HID, yr, mo FROM `AP supervisory visits`);
Empty set (0.34 sec)
mysql> SELECT HID, yr, mo FROM AP
-> WHERE (HID, yr, mo) NOT IN(SELECT DISTINCT HID, yr, mo FROM `AP supervisory visits`);
Empty set (0.47 sec)
mysql> SELECT HID, yr, mo FROM AP
-> WHERE (HID, yr, mo) NOT IN(SELECT DISTINCT * FROM (SELECT DISTINCT HID, yr, mo FROM `AP supervisory visits`) AS temp);
Empty set (3.04 sec)
mysql> SELECT HID, yr, mo FROM AP
-> WHERE (HID, yr, mo) IN(SELECT DISTINCT HID, yr, mo FROM `AP supervisory visits`) LIMIT 5;
+-----+------+----+
| HID | yr | mo |
+-----+------+----+
| 109 | 2011 | 03 |
| 109 | 2012 | 05 |
| 109 | 2012 | 06 |
| 110 | 2010 | 11 |
| 110 | 2010 | 12 |
+-----+------+----+
5 rows in set (0.00 sec)
我创建了一个临时表,其中包含HID,yr,mo,的所有不同组合,但我宁愿不使用临时表。上面的第三个查询应该是在内存中创建一个具有不同值的临时表(我知道这很难看)但似乎并非如此。
我的临时解决方案':
mysql> CREATE TABLE myTempAPSup SELECT DISTINCT HID, yr, mo FROM `AP supervisory visits`;
mysql> ALTER TABLE myTempAPSup ADD PRIMARY KEY(HID, yr, mo);
mysql> SELECT HID, yr, mo FROM AP
-> WHERE (HID, yr, mo) NOT IN (SELECT HID, yr, mo FROM myTempAPSup) LIMIT 5;
+-----+------+----+
| HID | yr | mo |
+-----+------+----+
| 109 | 2010 | 01 |
| 109 | 2012 | 01 |
| 109 | 2012 | 02 |
| 109 | 2012 | 03 |
| 109 | 2012 | 04 |
+-----+------+----+
5 rows in set (0.00 sec)
有没有办法让没有“孩子”的行获得'从这么糟糕的桌子?我认为我的麻烦源于缺乏独特/主键,但是我错过了其他一些语法错误'?
答案 0 :(得分:2)
如果你来自Oracle背景,左连接的想法,然后检查null可能看起来很奇怪。这个解决方案虽然很快,但是你并没有扫描联接表中的每个记录。另一种方法是使用相关子查询和not exists子句。
SELECT a.HID
, a.yr
, a.mo
FROM AP a
WHERE NOT EXISTS (
SELECT v.HID
FROM `AP supervisory visits` v
WHERE v.HID = a.HID
AND v.yr = a.yr
AND v.mo = a.mo
)
答案 1 :(得分:1)
您可以使用LEFT JOIN
并检查是否有子记录,如果不存在则为空。
select a.HID, a.yr, a.mo
from AP a
left join `AP supervisory visits` b on a.HID = b.HID and a.yr = b.yr and a.mo = b.mo
where b.yr is null;
答案 2 :(得分:1)
以下是获取AP
中没有“匹配”行的AP supervisory visits
行的一种方法:
SELECT a.HID
, a.yr
, a.mo
FROM AP a
LEFT
JOIN `AP supervisory visits` v
ON v.HID = a.HID
AND v.yr = a.yr
AND v.mo = a.mo
WHERE v.HID IS NULL
这是一个左外连接,用于从AP获取所有行,以及来自AP supervisory visits
的匹配行。 “技巧”是WHERE
子句中的谓词...我们排除了所有匹配的行。 (如果匹配,我们检查一个我们知道非NULL的列;如果没有匹配,列的唯一方法就是NULL。