MySQL查询,只为查询生命存储一些计算数据

时间:2015-08-06 16:45:20

标签: mysql

我有以下MySQL查询

SELECT
    (m.speed *  TIMESTAMPDIFF(MINUTE, m.arrival, m.departure) ) AS distance_traveled,
    (m.origin_x + distance_traveled) AS new_x,
    (m.origin_y + distance_traveled) AS new_y,
    m.city_id
FROM missions AS m
WHERE
        (new_x >= 1 AND new_x <= 15)
    AND
        (new_y >= 1 AND new_y <= 15)

有没有办法将distance_traveled用作此查询的变量?每次在同一查询中需要时,我都不想计算相同的数学。

此查询当前输出错误

Unknown column 'distance_traveled' in 'field list'

谢谢!

3 个答案:

答案 0 :(得分:1)

Mysql仍然没有实现常量表表达式,因此我们需要为这一个去旧学校:

SELECT
    m.distance_traveled,
    m.new_x,
    m.new_y,
    m.city_id
FROM (
        SELECT 
            `missions`.*, 
            (speed *  TIMESTAMPDIFF(MINUTE, arrival, departure)) AS distance_traveled,
            (speed *  TIMESTAMPDIFF(MINUTE, arrival, departure)) + origin_x AS new_x,
            (speed *  TIMESTAMPDIFF(MINUTE, arrival, departure)) + origin_y AS new_y
        FROM `missions`
    ) m
WHERE
    m.new_x >= 1 AND m.new_x <= 15
AND
    m.new_y >= 1 AND m.new_y <= 15

答案 1 :(得分:1)

不幸的是,MySQL没有为from子句提供方便,可靠和高效的解决方案。子查询最终会实现。变量是不可靠的。

但是,它确实扩展了此案例的having子句。因此,您可以将where替换为having并执行:

SELECT (m.speed *  TIMESTAMPDIFF(MINUTE, m.arrival, m.departure) ) AS distance_traveled,
       (m.origin_x + (m.speed *  TIMESTAMPDIFF(MINUTE, m.arrival, m.departure) )
       ) AS new_x,
       (m.origin_y + (m.speed *  TIMESTAMPDIFF(MINUTE, m.arrival, m.departure) )
       ) AS new_y,
       m.city_id
FROM missions  m
HAVING (new_x >= 1 AND new_x <= 15) AND
       (new_y >= 1 AND new_y <= 15)

答案 2 :(得分:0)

你可以摒弃这个会话变量技巧,但对它们的可靠程度的看法差异很大:

编辑:由于另一个答案让我注意到,结果字段正在WHERE中使用,它在HAVING中可能是安全的,但即便如此,我也不再建议它只是为了缩短您的查询。

编辑#2:由于评论太多,我不愿意删除答案;相反,我会添加内联注释以显示错误。

SELECT
    @someVar := (m.speed *  TIMESTAMPDIFF(MINUTE, m.arrival, m.departure) ) AS distance_traveled,
    (m.origin_x + @someVar) AS new_x,
    (m.origin_y + @someVar) AS new_y,
    m.city_id
FROM missions AS m
WHERE
        (new_x >= 1 AND new_x <= 15) // Referencing aliases from the SELECT
    AND                              // is not allowed; those values are not
        (new_y >= 1 AND new_y <= 15) // actually determined until after the 
                                     // WHERE is evaluated. Even if that 
                                     // were not the case, crossing clauses
                                     // with session variables (which this 
                                     // effectively does) is a recipe for 
                                     // disaster.
;