2016-01-18 2 views
0

У меня есть таблица под названием «пользователи». Внутри пользователей есть 3 столбца: id, name, birth_date (например: '2015-10-25').SQL-помощь, необходимая для запроса на день рождения

Я хочу сделать запрос, который возвращает идентификаторы пользователей, у которых есть дни рождения сегодня. Так я придумал:

SELECT id FROM users WHERE timestampdiff(day, cast(('2015' + '-' + extract(month from date) + '-' + extract(day from date)) as date), now()) % 365 = 0; 

Это не работает, но это:

SELECT id FROM users WHERE timestampdiff(day, birth_date, now()) % 365 = 0; 

** Это работает потому, что год в записи составляет 2015, что больше, чем 2012 , который является первым високосным годом, уходящим с настоящего времени. Так, если год в записи будет в период между 2012 и 2007, приведенный выше запрос должен быть различным для того, чтобы работать и показывать идентификатор человека день рождения:

SELECT id FROM users WHERE timestampdiff(day, birth_date, now()) % 365 = 1; 

Так что каждые 4 года далее, увеличивает номер ,

Вопрос в том, можно ли объединить строки внутри функций литья и использовать литые внутри timestampdiff? Первый запрос попытается заменить год в записи birth_date. Это необходимо для того, чтобы избежать различий в значениях модуля в течение високосного года, чтобы сохранить его 0. Заранее благодарим!

+2

Почему бы вам не делать «где месяц (birth_date) = month (now()) И day (birth_date) = day (now()) '? – jae555

+0

, потому что мне действительно нужны пользователи, у которых есть bdays за 7 дней, поэтому я не могу использовать месяц и день, потому что, если, например, у меня есть bday во 2-м месяце, это не сработает. Мне нужно что-то, чтобы дать мне разницу в 7 дней. – user3274898

ответ

1

Вопрос: Можно ли объединить строки внутри функций литья и использовать литые внутри timestampdiff?

A: Да, в этом контексте можно выполнить конкатенацию строк. (Но я не могу понять, почему это было бы необходимо, чтобы решить вашу проблему сообщалось.)

В MySQL конкатенация выполняется с помощью функции CONCAT, и оператору + Числовой оператор сложения. Но опять же, я не знаю, почему вы хотите выполнить конкатенацию строк.

Если вы хотите заменить «год» часть значения birth_date, вы можете использовать выражение вроде этого:

CONCAT('2016-',DATE_FORMAT(birth_date ,'%m-%d')) 

Предполагая, что birth_date столбца DATE типа данных, то вы могли бы что-то вроде это для форматирования значений даты в строки в формате «день месяца», который можно сравнить.

WHERE DATE_FORMAT(birth_date ,'%m-%d') = DATE_FORMAT(NOW() ,'%m-%d') 

Вы также можете проверить birth_date значения, которые соответствуют определенный день:

WHERE DATE_FORMAT(birth_date ,'%m-%d') = '01-17' 

Или что матч в тот день, семь дней с сегодняшнего дня:

WHERE DATE_FORMAT(birth_date ,'%m-%d') = DATE_FORMAT(NOW() + INTERVAL 7 DAY ,'%m-%d') 
+0

Отлично, это понятно и точно, что мне нужно. Особенно последний запрос. Спасибо! – user3274898

+0

Есть еще загадка значений 'birth_date', содержащих 29 февраля **' yyyy-02-29' **. Некоторые ребята выбирают праздновать свой день рождения 28 февраля, другие выбирают 1 марта. Как это условие обрабатывается, вероятно, зависит от цели использования «birth_date» (дата празднования, рассылка поздравительных открыток, определение возрастных изменений для страхования, выход на пенсию и т. Д.), И соответствующее обращение может быть сообщено применимыми правилами и политиками. – spencer7593

0

Почему бы не использовать интервал года ? И, хотя это может выглядеть сложным, если вы не запускаете функции по индексам данных, их можно использовать в выполнении запроса.

SQL Fiddle

MySQL 5.6 Настройка схемы:

CREATE TABLE users 
    (`id` int, `name` varchar(3), `birth_date` datetime) 
; 

INSERT INTO users 
    (`id`, `name`, `birth_date`) 
VALUES 
    (1, 'apm', '1985-01-18 00:00:00'), 
    (1, 'bpm', '1955-01-18 00:00:00'), 
    (1, 'cpm', '1955-01-19 00:00:00') 
; 

Запрос 1:

select 
     users.* 
    , date_sub(curdate(), INTERVAL concat(year(curdate()) - year(birth_date),'') YEAR) as calc_date 
from users 
where birth_date = date_sub(curdate(), INTERVAL concat(year(curdate()) - year(birth_date),'') YEAR); 

Results:

| id | name |    birth_date |     calc_date | 
|----|------|---------------------------|---------------------------| 
| 1 | apm | January, 18 1985 00:00:00 | January, 18 1985 00:00:00 | 
| 1 | bpm | January, 18 1955 00:00:00 | January, 18 1955 00:00:00 | 
+0

MySQL может использовать соответствующий индекс, да. Но запрос этой формы не может использовать операцию сканирования «диапазон» индекса. Да, 'birth_date' - пустой столбец (слева). Но выражение с правой стороны содержит ссылку на тот же столбец. Таким образом, это выражение должно оцениваться для каждой строки. Это будет полная проверка всех строк. – spencer7593

+0

Хорошая точка, спасибо, но это не изменяет общий случай (исключая функции по данным). Кроме того, я предпочитаю использовать математику даты. (Это может решить проблему 29 февраля, непроверенную.) –

Смежные вопросы