?

Log in

No account? Create an account

rauf


Блог Алиева Рауфа

О жизни и о себе


Previous Entry Поделиться Next Entry
Задачка по SQL
rauf
Кому интересно -- задачка не из самых простых. Думаю, неплохая задачка для верстальщиков и программистов, когда их на работу принимаешь :) Мне только что понадобилось ее по одному из проектов реализовать. Потерял минут 15, даже думал, неужели она столь нестандартна, что у меня уже голова кругом идет :) Оказалось, ничего.. решается несложно.

Есть таблица birthdays, следующей структуры:
 CREATE TABLE birthdays (
  day date default NULL,
  name varchar(255) default NULL,
) ;
INSERT INTO birthdays VALUES ('1978-02-01','Rauf Aliev');
INSERT INTO birthdays VALUES ('1977-05-01','Nadya Shulga');

Нужно ОДНИМ SQL-запросом получить следующую таблицу:
 Nadya Shulga -               6      
 Rauf Aliev   -          283 

(данные, разумеется, актуальны на сегодняшний день, 25 апреля 2004 года)

То есть в первом столбце имя -- во втором -- количество дней до ближайшего дня рождения. Соответственно, сортировка по этому значению по возрастанию. Если хоть кому-то надо, SQL-запрос приведу в комментах через несколько дней.


  • 1
Немного опоздал, но любопытно просто (данный запрос для MySQL)
Удалось только вывести число дней... хм как сделать сортировку не пойму
SELECT для оставшихся дней
IF(SIGN(DAYOFYEAR(day)-DAYOFYEAR(CURDATE()))+1,DAYOFYEAR(day)-DAYOFYEAR(CURDATE()),DAYOFYEAR(day)-DAYOFYEAR(CURDATE())+DAYOFYEAR(DATE_FORMAT(CURDATE(),"%y-12-31")))

решение в лоб :)
я не применял SIGN, DATE_FORMAT, к тому же, думаю, сортировку из того, что ты предложил все же реально сделать..

SELECT name, IF(SIGN(DAYOFYEAR(day)-DAYOFYEAR(CURDATE()))+1,DAYOFYEAR(day)-DAYOFYEAR(CURDATE()),DAYOFYEAR(day)-DAYOFYEAR(CURDATE())+DAYOFYEAR(DATE_FORMAT(CURDATE(),"%y-12-31"))) as a FROM birthdays order by a;

Но это не самое красивое решение использовать функцию DATE_FORMAT :)

О да, надо было as использовать... но в пнд торможу видимо ;)
DATE_FORMAT согласен - но тогда в моём случае не узнаешь сколько точно дней в году...
Что-то более хитрого решения пока не приходит в голову, буду с интересом ждать ответа ;)

что-то я не понял в чем проблема? кажется в любом sql есть функция переводящая дату в количество дней... дальше -- тривиально. нет?

В том-то и дело, что функция есть -- to_days, например в MySQL, но оно не всегда помогает. Ведь в базе же хранится не ближайший день рождения в будущем, а день рождения в году рождения, то есть, в моем случае, 01.02.1978. Следовательно, система должна находить, в этом году был у меня уже д.р. или нет, и в любом случае рапортовать, сколько до него дней осталось. Вот, собственно и все :)

Причем сделать надо именно одним SQL-запросом. Ясен хрен, что и без SQL это можно сделать на одной программной логике.

А вот так :-)

(Anonymous)
select
  *,
  concat(
    year(curdate()) +
    if(date_format(day,'%m-%d') < date_format(now(),'%m-%d'), 1, 0),
    date_format(day,'-%m-%d')
  ) as birthday

from
  birthdays

order by
  birthday

Как все же я сделал...

Не знаю, лучше это или хуже, но вот так:
select 
name, date_format(day, '%d.%m.%Y') as bd, 
                 ((-to_days(now())+
                 to_days(date_add(day, interval 
                     year(now())-year(day)+1 year))) 
                  % 
                  ((to_days(date_add(day, interval 1 year))) - 
                   (to_days(day)))) as daystobirthday 
from birthdays 
order by daystobirthday

select
	*,
	dayofyear(day) + if(dayofyear(day) < dayofyear(now()), 365, 0) as timeCounter
from
	birthdays
order by
	timeCounter

Неправильно привязываться к тому, что в году 365 дней, это в четверти случаев не так :) Во-вторых, неверно -- вот у меня 2 января д.р., это второй день в году, поскольку 2 < числоднейдосегодняшнегодня, то подставляется 365. Следовательно, 365+2=367 совсем не равно реальному числу дней от сегодняшнего дня.

ВОобщем, твой ответ после незначиетльной правки превращается в другие выше. Использовать IF нехорошо :)

А почему if - нехорошо. не думаю что операция сравнения выполняется медленнее чем вычитание.

Вот кстати самый распоследний вариант :) С количеством дней до ДР.
select
	*,
	dayofyear(day) - 
	dayofyear(now()) + 
	if(dayofyear(day) < dayofyear(now()), to_days(date_add(day, interval 1 year)) - to_days(day), 0) as timeCounter
from
	birthdays
	
order by
	timeCounter


Последний вариант, с учетом високосного года
select
	*,
	dayofyear(day) + 
	if(dayofyear(day) < dayofyear(now()), to_days(date_add(day, interval 1 year)) - to_days(day), 0) as timeCounter
from
	birthdays
order by
	timeCounter

Это работает _только_ на MySql, btw

(Anonymous)
сапж

  • 1