Предлагаю в данный топик складывать полезные сложные SQL запросы/процедуры/функции, дабы каждый из нас не создавал собственный велосипед, а мог бы взять хорошее, быстрое, удобное и работающее решение и применить его. Первым внесу свою лепту. Это процедураб которая вычисляет, сколько осталось дней до дня рождения человека (на основе даты его рождения) и возраст человека. Учитываються такие факторы как високосный год. Тип поля должен быть DATETIME или любого другого схожего типа. prf_age - возраст пользователя (integer) prf_days_left - кол-во дней до дня рождения. Если равно 0, значит у человека день рождение. У процедуры 1 параметр, который принимает ID пользователя, которому надо обновить данные. Если он равен NULL, то пересчитывает для всей таблицы. Запускать ежедневно в полночь. Код (Text): CREATE PROCEDURE `check_birthday`(in_prf_id INTEGER(11)) NOT DETERMINISTIC SQL SECURITY DEFINER COMMENT '' BEGIN DECLARE days_in_year INTEGER DEFAULT IF(DATE_FORMAT(CURDATE(), "%m%d") = "0229", 365, IF(IFNULL(DATE(CONCAT(IF(MONTH(CURDATE()) > 2, YEAR(CURDATE())+1, YEAR(CURDATE())), "-02-29")), 0) = 0, 365, 366)); UPDATE profiles SET prf_age = TIMESTAMPDIFF(YEAR, prf_birthday, NOW()), prf_days_left = IF((@days := ABS(TIMESTAMPDIFF(DAY, prf_birthday + INTERVAL TIMESTAMPDIFF(YEAR, prf_birthday, CURDATE())+1 YEAR, CURDATE()))) = days_in_year, 0, @days) WHERE IF(in_prf_id IS NULL, TRUE, FALSE) OR prf_id=in_prf_id; END; Разрабатывалось и тестировалось на реальном проэкте, на таблице в 24 000 записей, объёмом 5.5 мегабайт. По сравнению с приведущими вариантами просто молния Выслушаю конструктивные предложения, которые улучшат быстродействие
1 - подставить вместо двух полей свои поля народ я думаю в состоянии.. или мне вместо полей назвать table и birthday_field и age_field ? 2 - зачисти оффотп, пускай здесь будет только то что нужно, сообщение я могу подправить первое, если надо. Индивидуальность только в том, что там есть название таблицы и полей. Но это готовое решение, просто подставте поля, которые нужно вам, вот и всё.
Именно, ибо я например 3 раза переписывал, потому что тут народ реализовывал это в таком виде, что волосы шевелились не тока на голове (куча ифов, конкатов, date_format, substr и.т.д., убил бы, будь я главным программером), вообщем потрачено на это много времени, а полезна функция будет в любом месте, где надо понять, сколько человеку лет и сколько ему осталось до дня рождения. P.S. Я создавал топик с целью репозитария примеров, готовых решений, но это не значит что сделал copy/paste и будет работать. Это SQL, поля в базе у всех по разному будут в любом случае называться. Кому надо, подправят или выкинут лишнее.
Ага. Если этого ежа, взять, и бережно держа... впрочем, он наверно сдохнет, но идея хороша! Ладно, оффтоп к утру почищу, Репозиторий... согласен, готовые решения можно где нить складывать. Тоже обдумаю.
Psih, ужас какой... не проще ли сразу хранить в базе timestamp и манипуляци производить на php при выводе?
dark-demon, как выбирать пользователей у которых до дня рождения осталось меньше, например, двух недель?
Mavir, гы гы гы Доктор, я написал функцию сложения two_plus_two(), она умеет складывать 2+2, для сложения 2+3 используйте функцию two_plus_three() Что значит ругается? Работает то только в mysql 5.x, думать надо было А и имя таблицы надо было поменять, и еще поля заменить - она знак плюс читает там где то Много видел кривых и непонятных кодов откоторых ругался, вот толи дело мой
dark-demon, +1 Mavir, блин я не внимательно прочитал думал ты задаешь вопрос на первый пост топика но все равно гы гы гы
Нет, не проще, потому что: Так ты знаешь сколько у человека до дня рождения + ничего не надо вычислять на ходу (а вычисления сам видишь какие, они неплохо грузят сервак) - выигрываешь в производительности солидно. Второе - у меня есть задача выводить пользователей, у которых 30 и менее дней до дня рождения. 3 - тут же считается возраст пользователя. Если у него сегодня день рождение, то соответственно его возраст тоже обновится. 4 - в базе КУДА проще работать с датами, настолько же прозрачно, насколько это прозрачно с числами. В PHP ты бы замучался реализовывать это + у тебя бы это сожрало хорошее кол-во CPU time. А у меня не домашняя страничка, там 1 неоптимизированный запрос или PHP функция может весь сайт положить, потому что даже небольшая задержка помноженная на кол-во запросов к серверу приводит к хорошим тормозам. 5 - Так что учите SQL, он важнее чем PHP даже для хорошего WEB программера
Вот уж вычислить кол-во дней/лет и.т.д. между двумя датами, с учётом високосных лет и.т.д., я думаю будет сложновато и весьма неэфективно на PHP Зачем это делать на PHP, когда SQL справиться с этим лучше и куда быстрее Хотя бы "дата рождения + кол-во лет пользователя" и получить правильную дату, с учётом високосного (и не одного) года Вам нужен этот гемморой? P.S. У меня оптимизированный запрос + выполняется раз в сутки в 12 ночи, когда народу на сайте не очень много. Отрабатываает он быстро и совсем незаметно. Я даже представить не могу реализацию этого на PHP - насколько бы это было громоздко и медленно, да ещё и на каждого пользователя обработать надо данные. А что вы будете делать когда пользователей будет 100-200 тысячь? Тоже выбирать в PHP результат и гонять этот мега-масив (одна выборка займёт в разы больше времени, чем отработка запроса в недрах SQL сервера)?
Psih, извиняюсь за такой вопрос... тебе известно о функциях strtotime(), date()? Скорее всего это ошибочное мнение . PHP: <?$time = strtotime("+10 year", $time_brithday);?> и в чем тут гемор?
Элементарно ватсон, я даже не буду объяснять, просто приведу первый же комент в официальном мануале Хотя бы уже это. Не забывайте, мы работаем не с текущими датами в пределах года или двух, а с куда более широкими диапазонами, так что UNIX TIMESTAMP тут просто не годиться уважаемый. Да, в жтом случае решение есть, но немного притянутое зауши, хоть, соглашусь, и элегантное. Но опять же, попадись нам дата меньше чем 1970-01-01 - мы в пролёте. Следующий же ответ выявляет проблему, решение которой.. Снова SQL. И.т.д... Куча нюансов, хаков и.т.д., + куда меньше функций для манипулирования датами, всё надо писать самому. Я даже не хочу вдаваться в подробности проблемы, потому что там просто куча условий, нюансов, неудобностей и.т.д.
это называется не стандартной задачей, так же как не стоит забывать что существуют года до нашей эры И тут тип datetime так же бессилен. В большинстве решаемых задач даты от эпохи юникса достаточно. Так же как большинству задач хватает нашей эры . так что не забывайте люди живут ... давно Если Вы скажите, что ваша процедура не посчитает сколько лет человеку родившимуся в 4013 году до нашей эры, мое сердце будет разбито
vb Уж извините, база данных не поддерживает такие даты, да и пример ваш выдуман уж сильно Покажите мне базу данных которая поддерживает даты до нашей эры MySQL точно не умеет, он умеет только
Я же не базу придумываю, а задачу. Это в качестве примера о не стандартных задачах. Так же для большинства решений достаточно даты в формате секунд от начала эпохи юникса. p.s. не могли бы вы НЕ переписывать дописывать полностью свои посты. А то как то тупо получается вроде уже ответил на вопрос, а пост уже переписан пару раз.