这有点奇怪:我有以下MySQL存储过程(或函数),除非需要了解全貌,否则大多数都可以安全地忽略。问题是ORDER BY子句。
BEGIN
SELECT DISTINCT e.*, ( 3959 * acos( cos( radians(in_latitude) ) * cos( radians( e.address_latitude ) )
* cos( radians(e.address_longitude) - radians(in_longitude)) + sin(radians(in_latitude))
* sin( radians(e.address_latitude)))) AS distanceFromUsersPostcode
FROM event e
INNER JOIN event_organiser eo on e.event_organiser_id = eo.id
WHERE (e.event_name LIKE in_search OR e.address_town LIKE in_search OR e.address_county LIKE in_search OR eo.event_organiser_name LIKE in_search)
AND e.start_date_time >= in_start_date
AND e.start_date_time <= in_end_date
AND e.enabled = true
HAVING distanceFromUsersPostcode < in_maxDistanceFromUser
/*
* 1 *
ORDER BY distanceFromUsersPostcode
* 2 *
ORDER BY IF(in_orderBy='LOCATION', CAST(distanceFromUsersPostcode AS DECIMAL), e.start_date_time) ASC;
*/
ORDER BY
CASE in_orderBy
WHEN 'LOCATION' THEN distanceFromUsersPostcode
ELSE e.start_date_time
END
ASC;
END
现在的问题是,当前未注释的ORDER BY子句似乎将DECIMAL值distanceFromUsersPostcode视为VARCHAR(或字符串)值。
它以以下形式订购结果:
0.4,101.9,10.2.8,11.1,11.9
如果我使用标记为* 2 *
的变体,也可以这样说但是,如果我恢复标记为* 1 *的原始变体,结果将按预期排序:
0.4,11.1,11.9,101.9,102.8
我的猜测是,如果在IF函数(* 2 *)中使用,则将distanceFromUsersPostcode变量视为VARCHAR,因此我尝试将其转换为DECIMAL。然而,这没有效果。
任何人都可以了解这里发生的事情吗?
以下行为符合预期,但当然不是很优雅,因为它会复制整个查询:
BEGIN
IF in_orderBy='LOCATION' THEN
SELECT DISTINCT e.*, ( 3959 * acos( cos( radians(in_latitude) ) * cos( radians( e.address_latitude ) )
* cos( radians(e.address_longitude) - radians(in_longitude)) + sin(radians(in_latitude))
* sin( radians(e.address_latitude)))) AS distanceFromUsersPostcode
FROM event e
INNER JOIN event_organiser eo on e.event_organiser_id = eo.id
WHERE (e.event_name LIKE in_search OR e.address_town LIKE in_search OR e.address_county LIKE in_search OR eo.event_organiser_name LIKE in_search)
AND e.start_date_time >= in_start_date
AND e.start_date_time <= in_end_date
AND e.enabled = true
HAVING distanceFromUsersPostcode < in_maxDistanceFromUser
ORDER BY distanceFromUsersPostcode;
ELSE
SELECT DISTINCT e.*, ( 3959 * acos( cos( radians(in_latitude) ) * cos( radians( e.address_latitude ) )
* cos( radians(e.address_longitude) - radians(in_longitude)) + sin(radians(in_latitude))
* sin( radians(e.address_latitude)))) AS distanceFromUsersPostcode
FROM event e
INNER JOIN event_organiser eo on e.event_organiser_id = eo.id
WHERE (e.event_name LIKE in_search OR e.address_town LIKE in_search OR e.address_county LIKE in_search OR eo.event_organiser_name LIKE in_search)
AND e.start_date_time >= in_start_date
AND e.start_date_time <= in_end_date
AND e.enabled = true
HAVING distanceFromUsersPostcode < in_maxDistanceFromUser
ORDER BY e.start_date_time;
END IF;
END
答案 0 :(得分:0)
因为你使用不同的数据类型进行排序mysql会尝试将它们转换为方便的值来比较它们。在您的特定情况下,它将转换为字符串。因此将distanceFromUsersPostcode
转换为数字是没有意义的,因为它将被转换回字符串。您需要以方便的格式转换字符串以进行数字排序。 LPAD功能会在这里帮到你。
ORDER BY
CASE in_orderBy
WHEN 'LOCATION' THEN LPAD(CAST(distanceFromUsersPostcode as CHAR),6)
ELSE e.start_date_time
END
ASC;