这是我的设置:
表 records
包含多个(超过两个)PKID 列以及一些其他列。
表 cached_records
只有两列,与 records
的两个 PKID 相同。
例如,假设 records
具有 PKID“keyA”、“keyB”和“keyC”,而 cached_records
只有“keyA”和“keyB”。
我需要从 records
表中提取相应的 PKID(因此,'keyA' 和 'keyB')不在 cached_records
表中的行。
如果我只使用一个 PKID,我知道这项任务会多么简单:
SELECT
pkid
FROM
records
WHERE
pkid NOT IN (SELECT pkid FROM cached_records)
但是,有两个 PKID 的事实意味着我不能使用简单的 NOT IN
。这是我目前拥有的:
SELECT
`keys`.`keyA` AS `keyA`,
`keys`.`keyB` AS `keyB`
FROM
(
SELECT DISTINCT
`keyA`,
`keyB`
FROM
`records`
) AS `keys`
LEFT JOIN
`cached_records` AS `cached`
ON
`keys`.`keyA` = `cached`.`keyA`
AND
`keys`.`keyB` = `cached`.`keyB`
WHERE
(
`cached`.`keyA` IS NULL
AND
`cached`.`keyB` IS NULL
)
(DISTINCT
是必需的,因为我只是从 records
表中获取多个 PKID 中的两个,所以可能有重复项,我真的不需要重复项; 'keyC' 未被使用,它有助于确定记录的唯一性)。
上面的这个查询工作得很好,但是,随着 cached_records
表的增长,查询的处理时间越来越长(我们现在说的是几分钟,有时需要足够长的时间以至于我的代码挂起并且崩溃)。
所以,我想知道使用多个 PKIDS 而不是一个 PKIDS 来执行这种操作(从一个表中选择行不存在于另一个表中的行)最有效的方法是什么...
最佳答案
这应该更快:
SELECT DISTINCT
`records`.`keyA` AS `keyA`,
`records`.`keyB` AS `keyB`
FROM
`records`
LEFT JOIN
`cached_records` AS `cached`
ON
`records`.`keyA` = `cached`.`keyA`
AND
`records`.`keyB` = `cached`.`keyB`
WHERE
`cached`.`keyA` IS NULL -- one is enough here
注意事项:
- 将查询作为表,你会损失很多性能。您可以在此处的最外面的 SELECT 中执行不同操作。
- 检查两个键中的一个是否为空就足够了,因为没有一个可以为空
- 您应该验证
keyA
和keyB
列的类型相同,并且没有发生转换(在工作的实时代码中看到这样...) - 你应该在表上有适当的索引。此查询的分钟数表明发生了一些可怕的事情......(或大量数据)
关于mysql - 如何选择一个表中的记录而不是另一个具有多个 PKID 的记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13002062/