下面的函数(+用法示例)实现了一些我需要在一个相当复杂的select查询中使用的业务逻辑,它已经将我们的数据库服务器推向了它的极限。下面的代码(复制/粘贴;-)使用2选项CSV运行大约35毫秒(没有删除和创建);我需要加快速度......
它的作用
在endDate之前从CSV选项中给我一个更晚的startDate,或者 - 当endDate无效时 - 在startDate之后。
DROP FUNCTION IF EXISTS later_start_before_end_date;
delimiter $$
CREATE FUNCTION later_start_before_end_date(startDate DATETIME, endDate DATETIME, optionsCSV CHAR(255))
RETURNS DATETIME
-- COMMENT "Choose the latest alternative start-datetime from a comma-separated optionsCSV of UNIX timestamps that is inbetween startDate DATETIME and endDate DATE"
-- COMMENT "endDate value of NULL will be interpreted as INDEFINITE"
BEGIN
-- SET @optionsCSV = CONCAT(optionDate1, ',', optionDate2); -- e.g. "2002-10-10 02:01:00,2005-10-10 23:21:00"
SET @isIndefiniteEnd = (ISNULL(endDate) OR endDate LIKE("0000-00-00%"));
SET @returnValue = startDate;
WHILE (NOT ISNULL(optionsCSV) AND (optionsCSV) != '') DO
SET @strLen = LENGTH(optionsCSV);
SET @altDate = STR_TO_DATE(SUBSTRING_INDEX(optionsCSV, ',', 1), '%Y-%m-%d %H:%i:%s');
SET @isAfterNewStart = (TIMESTAMPDIFF(SECOND, @returnValue, @altDate) > 0);
CASE (@isAfterNewStart)
WHEN 1 THEN
SET @isBeforeEnd = (NOT @isIndefiniteEnd /* timestampdiff cannot calculate null or zero date! */
AND TIMESTAMPDIFF(SECOND, endDate, @altDate) < 0);
CASE (@isIndefiniteEnd OR @isBeforeEnd)
WHEN 1 THEN
SET @returnValue = @altDate;
ELSE BEGIN END;
END CASE;
ELSE BEGIN END;
END CASE;
SET @subStrLen = LENGTH(SUBSTRING_INDEX(optionsCSV, ',', 1));
SET optionsCSV = MID(optionsCSV, @subStrLen+2, @strLen);
END WHILE;
RETURN @returnValue;
END; $$
delimiter ;
/* Use it ... */
SET @startDate = STR_TO_DATE('2002-10-10 00:00:00', '%Y-%m-%d %H:%i:%s');
SET @endDate = STR_TO_DATE('2003-10-10', '%Y-%m-%d');
/* ... edge cases for the above start-end */
SET @optionsCSV = CONCAT(
-- TIMESTAMP('2002-10-10 00:00:00'),
-- ',',
-- TIMESTAMP('2002-10-10 00:00:01'),
-- ',',
TIMESTAMP('2003-10-10 00:00:00'),
',',
TIMESTAMP('2003-10-09 23:59:59')
);
/* ... or a single timestamp */
-- SET @optionsCSV = TIMESTAMP('2002-10-10 00:00:01');
SELECT later_start_before_end_date(@startDate, @endDate, @optionsCSV);
目标和注意事项
任何建议都受到高度赞赏。