有没有办法让select和where条件中的公式只计算一次?
我认为mysql必须对以下示例中的每一行进行两次计算。
SELECT z1.id sid1,z2.id sid2,SQRT(POW(ABS(z1.col-z2.col),2) + POW(ABS(z1.row-z2.row),2)) r
FROM stars z1,stars z2
WHERE z1.id!=z2.id
AND SQRT(POW(ABS(z1.col-z2.col),2) + POW(ABS(z1.row-z2.row),2)) <=32
ORDER BY z1.id,z2.id
答案 0 :(得分:2)
您不能引用SELECT
子句中WHERE
子句中定义的别名,但可以在HAVING
子句中使用它们。这是因为WHERE
在SELECT
之前进行了评估,因为SELECT
可能包含聚合函数。
SELECT z1.id sid1,z2.id sid2,SQRT(POW(ABS(z1.col-z2.col),2) + POW(ABS(z1.row-z2.row),2)) r
FROM stars z1,stars z2
WHERE z1.id != z2.id
HAVING r <= 32
ORDER BY z1.id,z2.id
请注意,HAVING
子句很可能不会在索引中使用。您可以为WHERE
子句提供一个近似术语,以便进行索引:
SELECT z1.id sid1,z2.id sid2,SQRT(POW(ABS(z1.col-z2.col),2) + POW(ABS(z1.row-z2.row),2)) r
FROM stars z1,stars z2
WHERE z1.id != z2.id
AND (z2.col BETWEEN z1.col-32 AND z1.col+32)
AND (z2.row BETWEEN z1.row-32 AND z1.row+32)
HAVING r <= 32
ORDER BY z1.id,z2.id
请注意,瓶颈是磁盘访问,而不是算术计算,因此如果您要优化速度,您可能希望继续使用WHERE并仅优化WHERE子句:
请注意
尝试:
SELECT z1.id sid1,z2.id sid2,
SQRT((z1.col-z2.col)*(z1.col-z2.col) + (z1.row-z2.row)*(z1.row-z2.row)) r
FROM stars z1,stars z2
WHERE z1.id != z2.id
AND (z1.col-z2.col)*(z1.col-z2.col) + (z1.row-z2.row)*(z1.row-z2.row) <= 1024
ORDER BY z1.id,z2.id
答案 1 :(得分:0)
请注意,你真的不需要计算这个表达式
SQRT(POW(ABS(z1.col-z2.col),2) + POW(ABS(z1.row-z2.row),2)) <=32
首先,您可以通过将表达式的两个部分都提升到幂2来避免计算SQRT,这通常是缓慢而非绝对准确的。此后它变为相等,但更准确和快速
POW(ABS(z1.col-z2.col),2) + POW(ABS(z1.row-z2.row),2) <= 1024
其次,你将ABS(z1.col-z2.col)提升到2,但你不需要ABS,因为它不会真正影响POW的结果。
z1.col = 4, z2.col = 2 => pow(4-2, 2) = pow(2,2) = 2*2 = 4
z1.col = 2, z2.col = 4 => pow(2-4, 2) = pow(-2,2) = -2*-2 = 4
所以,
POW(z1.col-z2.col,2) + POW(z1.row-z2.row,2) <= 1024
会使查询更快。