SQL 查询返回最近的重复项,但不返回非重复项
SQL query is returning most recent duplicates, but not non-duplicates
我有一个 MySQL table (MySQL 5.7),其中包含以下列:id(键)、电子邮件、百分比、file_name。 table 记录学生(通过电子邮件识别)完成某些活动的时间。
我需要 return 一个列表,每个 file_name 学生完成的内容都有一行。如果他们不止一次完成 file_name,我想 return 最近的尝试,基于自动递增的 id。我在这里使用了一些答案来创建以下查询。 file_name 字符串匹配用于隔离特定的 activity 类型和级别:
SELECT id,
file_name,
percentage
FROM users t1
WHERE email IN ('name@student.com')
AND file_name LIKE ('%IL%')
AND file_name LIKE ('%B2%')
AND id = ( SELECT MAX(id)
FROM users t2
WHERE t2.file_name = t1.file_name
)
GROUP BY file_name, percentage, id
ORDER BY id;
此查询成功 return 任何重复文件名的最新实例,但没有 return 任何非重复文件。所以,如果一个学生完成了 8 file_names 一次,但重复了 1 file_name 两次,这个查询只有 returns 一行,最近的重复。它应该 return 8 个 activity 行,加上最近的副本。
我知道了 运行 here 并且它按预期工作 - return 处理非重复项和最近的重复项,所以我不明白为什么它不是在数据库本身上工作。
我可以使用 CTE 成功执行此操作,但我无法控制数据库,因此无法升级以允许 CTE。
最大的问题是相关子查询正在获取 any 的 file_name
的最新 ID email
,而不仅仅是与外部查询匹配的电子邮件。此外,外部查询上的 GROUP BY
似乎是不必要的。
保持相同的相关子查询模式,我们可以这样做:
SELECT t1.id
, t1.email
, t1.file_name
, t1.percentage
FROM users t1
WHERE t1.email IN ('name@student.com')
AND t1.file_name LIKE ('%IL%')
AND t1.file_name LIKE ('%B2%')
AND t1.id = ( -- most recent id for (email,file_name)
SELECT MAX(t2.id)
FROM users t2
WHERE t2.email = t1.email
AND t2.file_name = t1.file_name
)
ORDER BY t1.id
对于大型集合,相关子查询模式可以吃掉我们的午餐和午餐盒,即使有适当的索引可用,因为对于外部查询处理的每一行(每一行),该子查询将获得 re-executed之前没有被另一个谓词排除)
我倾向于重写查询以避免相关子查询,并测量和比较性能并比较计划(EXPLAIN PLAN 输出。)
我们可以使用内联视图(MySQL 说法中的“派生 table”)获取最新的 id,然后连接回原始 table 以获取与该 id
关联的列
SELECT t1.id
, t1.email
, t1.file_name
, t1.percentage
-- , t2.*
FROM ( -- most recent id for (email,file_name)
SELECT MAX(t2.id) AS _most_recent_id
, t2.email
, t2.file_name
FROM users t2
WHERE t2.email IN ('name@student.com')
AND t2.file_name LIKE ('%IL%')
AND t3.file_name LIKE ('%B2%')
GROUP
BY t2.email
, t2.file_name
) t3
JOIN users t1
ON t1.id = t3._most_recent_id
ORDER
BY t1.id
注意:在将内联视图查询(SELECT 别名为 t3
)作为派生 table 合并到外部 [=44] 之前,我们可以对其进行测试和工作=].
在此示例中,t3
(内联视图查询)到 return 列 t2.email
或 t2.file_name
并不是绝对必要的。但它确实让验证结果变得更容易,我们得到了给定电子邮件的最高 ID 和 file_name。 (我们可以在另一个更简单的语句 SELECT * FROM users WHERE email = ? AND file_name = ?
中使用 returned 值来获取我们从中选择最大 ID 的整组行。
我有一个 MySQL table (MySQL 5.7),其中包含以下列:id(键)、电子邮件、百分比、file_name。 table 记录学生(通过电子邮件识别)完成某些活动的时间。
我需要 return 一个列表,每个 file_name 学生完成的内容都有一行。如果他们不止一次完成 file_name,我想 return 最近的尝试,基于自动递增的 id。我在这里使用了一些答案来创建以下查询。 file_name 字符串匹配用于隔离特定的 activity 类型和级别:
SELECT id,
file_name,
percentage
FROM users t1
WHERE email IN ('name@student.com')
AND file_name LIKE ('%IL%')
AND file_name LIKE ('%B2%')
AND id = ( SELECT MAX(id)
FROM users t2
WHERE t2.file_name = t1.file_name
)
GROUP BY file_name, percentage, id
ORDER BY id;
此查询成功 return 任何重复文件名的最新实例,但没有 return 任何非重复文件。所以,如果一个学生完成了 8 file_names 一次,但重复了 1 file_name 两次,这个查询只有 returns 一行,最近的重复。它应该 return 8 个 activity 行,加上最近的副本。
我知道了 运行 here 并且它按预期工作 - return 处理非重复项和最近的重复项,所以我不明白为什么它不是在数据库本身上工作。
我可以使用 CTE 成功执行此操作,但我无法控制数据库,因此无法升级以允许 CTE。
最大的问题是相关子查询正在获取 any 的 file_name
的最新 ID email
,而不仅仅是与外部查询匹配的电子邮件。此外,外部查询上的 GROUP BY
似乎是不必要的。
保持相同的相关子查询模式,我们可以这样做:
SELECT t1.id
, t1.email
, t1.file_name
, t1.percentage
FROM users t1
WHERE t1.email IN ('name@student.com')
AND t1.file_name LIKE ('%IL%')
AND t1.file_name LIKE ('%B2%')
AND t1.id = ( -- most recent id for (email,file_name)
SELECT MAX(t2.id)
FROM users t2
WHERE t2.email = t1.email
AND t2.file_name = t1.file_name
)
ORDER BY t1.id
对于大型集合,相关子查询模式可以吃掉我们的午餐和午餐盒,即使有适当的索引可用,因为对于外部查询处理的每一行(每一行),该子查询将获得 re-executed之前没有被另一个谓词排除)
我倾向于重写查询以避免相关子查询,并测量和比较性能并比较计划(EXPLAIN PLAN 输出。)
我们可以使用内联视图(MySQL 说法中的“派生 table”)获取最新的 id,然后连接回原始 table 以获取与该 id
关联的列SELECT t1.id
, t1.email
, t1.file_name
, t1.percentage
-- , t2.*
FROM ( -- most recent id for (email,file_name)
SELECT MAX(t2.id) AS _most_recent_id
, t2.email
, t2.file_name
FROM users t2
WHERE t2.email IN ('name@student.com')
AND t2.file_name LIKE ('%IL%')
AND t3.file_name LIKE ('%B2%')
GROUP
BY t2.email
, t2.file_name
) t3
JOIN users t1
ON t1.id = t3._most_recent_id
ORDER
BY t1.id
注意:在将内联视图查询(SELECT 别名为 t3
)作为派生 table 合并到外部 [=44] 之前,我们可以对其进行测试和工作=].
在此示例中,t3
(内联视图查询)到 return 列 t2.email
或 t2.file_name
并不是绝对必要的。但它确实让验证结果变得更容易,我们得到了给定电子邮件的最高 ID 和 file_name。 (我们可以在另一个更简单的语句 SELECT * FROM users WHERE email = ? AND file_name = ?
中使用 returned 值来获取我们从中选择最大 ID 的整组行。