SQL - 派生表中的未知列

时间:2013-06-06 20:19:07

标签: sql alias derived-table

这是我的查询中有问题的部分:

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子查询和派生表,如果我多次使用相同的子查询,效率会很低。

3 个答案:

答案 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可确保只返回一行。