这是我的查询中有问题的部分:
SELECT
(SELECT id FROM users WHERE name = 'John') as competitor_id,
(SELECT MIN(duration)
FROM
(SELECT duration FROM attempts
WHERE userid=competitor_id ORDER BY created DESC LIMIT 1,1
) x
) as best_time
执行时,会抛出此错误:
#1054 - 'where子句'中的未知列'competitor_id'
看起来派生表'x'无法看到父查询别名competitor_id
。有没有办法如何创建某种全局别名,所有派生表都可以使用它?
我知道我可以直接在WHERE子句中使用competitor_id
查询作为子查询,并且完全避免使用别名,但是我的真实查询要大得多,我需要更多地使用competitor_id
子查询和派生表,如果我多次使用相同的子查询,效率会很低。
答案 0 :(得分:0)
您可能不需要在select语句中使用派生表,以下不会完成同样的事情吗?
SELECT
users.id as competitor_id,
MIN(duration) as best_time
FROM users
inner join attempts on users.id = attempts.user_id
WHERE name = 'John'
group by users.id
答案 1 :(得分:0)
导致错误是因为select子句中引入的标识符不能从该子句中的任何其他地方引用 - 基本上,使用SQL,标识符/列被推送 out 而不是向下(或跨越)。
但是,即使有可能,以这种方式编写查询也不好。在用户和尝试之间使用JOIN(在用户ID上),然后根据名称进行过滤。然后,SQL查询规划器将采用高级关系代数并为其编写有效的计划:)请注意,不需要手动排序或限制,因为组上的聚合(MIN)处理它。
SELECT u.id, u.name, MIN(a.duration) as duration
FROM users u
-- match up each attempt per user
JOIN attempts a
ON a.userid = u.id
-- only show users with this name
WHERE u.name = 'John'
-- group so we get the min duration *per user*
-- (name is included so it can be in the output clause)
GROUP BY u.id, u.name
答案 2 :(得分:0)
关于你的查询的一些内容似乎很奇怪。最里面的子查询是选择一行,然后你正在使用min(duration)
。 min是不必要的,因为只有一行。您可以将查询短语为:
SELECT u.id as competitor_id, a.duration as best_time
from users u left outer join
attempts a
on u.id = a.userid
where u.name = 'John'
order by a.created desc
limit 1, 1;
这似乎是您的查询尝试执行的操作。但是,这可能不是你的意图。它可能是最近的时间。 (如果您使用的是MySQL,那么limit 1, 1
实际上是第二个最近的记录)。要获得最小的持续时间(可能是“最佳”),您可以这样做:
SELECT u.id as competitor_id, min(a.duration) as best_time
from users u left outer join
attempts a
on u.id = a.userid
where u.name = 'John'
添加group by u.id
可确保只返回一行。