DELIMITER $$ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`zone_getOptionsForShipment`(vShipped DATE, vShowExpiredZones BOOLEAN) BEGIN /** * Gets computed options for the passed zones and shipping date. * * @table tmp.zones(id) The zones ids * @param vShipped The shipping date * @return tmp.zoneOption(zoneFk, hour, travelingDays, price, bonus, specificity) The computed options */ DECLARE vHour TIME DEFAULT TIME(util.VN_NOW()); DROP TEMPORARY TABLE IF EXISTS tLandings; CREATE TEMPORARY TABLE tLandings (INDEX (eventFk)) ENGINE = MEMORY SELECT e.id eventFk, @travelingDays := IFNULL(e.travelingDays, z.travelingDays) travelingDays, TIMESTAMPADD(DAY, @travelingDays, vShipped) landed FROM tmp.zone t JOIN zone z ON z.id = t.id JOIN zoneEvent e ON e.zoneFk = t.id; DROP TEMPORARY TABLE IF EXISTS tmp.zoneOption; CREATE TEMPORARY TABLE tmp.zoneOption ENGINE = MEMORY SELECT * FROM ( SELECT t.id zoneFk, TIME(IFNULL(e.`hour`, z.`hour`)) `hour`, l.travelingDays, IFNULL(e.price, z.price) price, IFNULL(e.bonus, z.bonus) bonus, l.landed, vShipped shipped FROM tmp.zone t JOIN zone z ON z.id = t.id JOIN zoneEvent e ON e.zoneFk = t.id JOIN tLandings l ON l.eventFk = e.id WHERE ( e.`type` = 'day' AND e.`dated` = l.landed ) OR ( e.`type` != 'day' AND e.weekDays & (1 << WEEKDAY(l.landed)) AND (e.`started` IS NULL OR l.landed >= e.`started`) AND (e.`ended` IS NULL OR l.landed <= e.`ended`) ) ORDER BY zoneFk, CASE WHEN e.`type` = 'day' THEN 1 WHEN e.`type` = 'range' THEN 2 ELSE 3 END LIMIT 10000000000000000000 ) t GROUP BY zoneFk; DROP TEMPORARY TABLE tLandings; DELETE t FROM tmp.zoneOption t JOIN zoneExclusion e ON e.zoneFk = t.zoneFk AND e.`dated` = t.landed LEFT JOIN zoneExclusionGeo eg ON eg.zoneExclusionFk = e.id WHERE eg.zoneExclusionFk IS NULL; IF NOT vShowExpiredZones THEN DELETE FROM tmp.zoneOption WHERE vShipped < util.VN_CURDATE() OR (vShipped = util.VN_CURDATE() AND util.VN_CURTIME() > `hour`); END IF; END$$ DELIMITER ;