Mysql 如何避免SQL中的嵌套子查询
我刚刚在我的网站上添加了一个标签系统,我正试图找出运行可伸缩查询的最有效方法。下面是一个基本的mysql查询,用于返回给定用户的标记匹配:Mysql 如何避免SQL中的嵌套子查询,mysql,performance,subquery,inner-join,Mysql,Performance,Subquery,Inner Join,我刚刚在我的网站上添加了一个标签系统,我正试图找出运行可伸缩查询的最有效方法。下面是一个基本的mysql查询,用于返回给定用户的标记匹配: SELECT scans.scan_index, scans.scan_id, scans.archive_folder FROM tags INNER JOIN interpretationtags USING (tagid) INNER JOIN interpretations USING
SELECT
scans.scan_index,
scans.scan_id,
scans.archive_folder
FROM
tags
INNER JOIN
interpretationtags USING (tagid)
INNER JOIN
interpretations USING (interpretation_id)
INNER JOIN
scans
ON scans.scan_id = interpretations.scan_id
AND scans.archive_folder = interpretations.archive_folder
INNER JOIN
archives
ON scans.archive_folder = archives.archive_folder
WHERE
archives.user_id = "google-authd...."
AND tags.tag = "tag1"
但是,当我想查询多个标记
以进行相同的扫描
时,它会变得很粘。您可以看到,标记
存在于不同的解释中,
并且每个扫描都有多个解释。
下面是使用子查询的两个标记的工作查询:
SELECT
a.scan_index,
a.scan_id,
a.archive_folder
FROM
(
SELECT
scans.scan_index,
scans.scan_id,
scans.archive_folder
FROM
tags
INNER JOIN
interpretationtags USING (tagid)
INNER JOIN
interpretations USING (interpretation_id)
INNER JOIN
scans
ON scans.scan_id = interpretations.scan_id
AND scans.archive_folder = interpretations.archive_folder
INNER JOIN
archives
ON scans.archive_folder = archives.archive_folder
WHERE
archives.user_id = "google-auth2..."
AND tags.tag = "tag1"
)
as a
INNER JOIN
interpretations
ON a.scan_id = interpretations.scan_id
AND a.archive_folder = interpretations.archive_folder
INNER JOIN
interpretationtags USING(interpretation_id)
INNER JOIN
tags USING(tagid)
WHERE
tags.tag = "tag2"
因为这是在LAMP堆栈上运行的,所以我已经编写了一些PHP代码来迭代标记
,我想将其包含在这个和样式搜索中,从而构建一个多嵌套查询。这是一对三
SELECT
b.scan_index,
b.scan_id,
b.archive_folder
FROM
(
SELECT
a.scan_index,
a.scan_id,
a.archive_folder
FROM
(
SELECT
scans.scan_index,
scans.scan_id,
scans.archive_folder
FROM
tags
INNER JOIN
interpretationtags USING (tagid)
INNER JOIN
interpretations USING (interpretation_id)
INNER JOIN
scans
ON scans.scan_id = interpretations.scan_id
AND scans.archive_folder = interpretations.archive_folder
INNER JOIN
archives
ON scans.archive_folder = archives.archive_folder
WHERE
archives.user_id = "google..."
AND tags.tag = "tag1"
)
as a
INNER JOIN
interpretations
ON a.scan_id = interpretations.scan_id
AND a.archive_folder = interpretations.archive_folder
INNER JOIN
interpretationtags USING(interpretation_id)
INNER JOIN
tags USING(tagid)
WHERE
tags.tag = "tag2"
)
as b
INNER JOIN
interpretations
ON b.scan_id = interpretations.scan_id
AND b.archive_folder = interpretations.archive_folder
INNER JOIN
interpretationtags USING(interpretation_id)
INNER JOIN
tags USING(tagid)
WHERE
tags.tag = "tag3"
即使是4个嵌套的子查询也能以最少的数据快速运行,但在处理10万行数据时,我认为这不是一个可伸缩的解决方案。我如何才能在不恢复到这种低效的丑陋代码的情况下完成这项工作?如果没有表结构和示例数据,很难确定,但我认为这是在错误的方向上进行的。您应该从扫描开始,找到所有适当的标记,然后对这些标记进行筛选(然后在
表达式中使用一个简单的):
请注意,根据您的选择
字段列表,我认为您实际上根本不需要将加入到存档
。请参阅。此外,关于查询优化的问题总是需要对给定查询进行解释。谢谢Nick。这很接近,但它会得到所有使用tag1或tag2的扫描。@UltrasondJelly那么您想要使用tag1和tag2的扫描?你的问题不是100%清楚很抱歉,这是目标。你应该能够将按扫描分组。扫描索引,扫描id,扫描id,扫描存档文件夹(COUNT)(DISTINCT tags.tag)=2
添加到查询中以实现这一点。这在这里是可行的,但是如果使用tag1的同一扫描有两种解释呢?
SELECT
scans.scan_index,
scans.scan_id,
scans.archive_folder
FROM
scans
INNER JOIN
archives
ON scans.archive_folder = archives.archive_folder
INNER JOIN
interpretations
ON scans.scan_id = interpretations.scan_id
AND scans.archive_folder = interpretations.archive_folder
INNER JOIN
interpretationtags USING (interpretation_id)
INNER JOIN
tags USING (tagid)
WHERE
archives.user_id = "google-authd...."
AND tags.tag IN("tag1", "tag2")