这有点奇怪:我有以下的MySQL存储过程(或函数),大多数可以安全地忽略,除非需要了解完整的图片。问题是ORDER BY子句。现在ORDER BY子句的MySQL IF语句问题
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子句好像对待十进制值distanceFromUsersPostcode为VARCHAR(或字符串)值。
它订单的结果形式:
0.4,101.9,102.8,11.1,11.9
同样可以如果我用标记为* 2 *
所述变体然而说,如果我恢复到标记为* 1 *原来的变种,其结果将被责令按预期:
0.4,11.1,11.9,101.9,102.8
我的猜测如果在IF函数(* 2 *)内部使用了,则MySQL将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
感谢您的评论。它没有按照你的建议进行编译,而是将它改为LPAD(CAST(distanceFromUsersPostcode as CHAR),6,'0')用零填充到左边的pad。然而,不幸的是,它没有像预期的那样工作,就像以前一样。 –
但是,这让我想到了MySQL正在应用词法排序(所以这两种类型匹配)的事实。我设法通过使用WHEN'LOCATION'THEN(distanceFromUsersPostcode + 10000)来使查询工作。这已经解决了这个问题,但让我更加关注。 MySQL现在正在执行词法排序,而不是按数字(或日期)进行排序,具体取决于提供的排序。我在别处读过这可能会导致查询运行速度慢得多。如果是这种情况,我会更快乐地复制原来显示的代码段。不太优雅但更快速的查询。有什么想法吗? –
我很高兴你能工作。这种排序要求并不常见。你能不能以不同的方式思考你的要求? –