SQL: вычислить дату первого четверга года
Вопрос из тренажера: https://sql-validator.ru/task/birthdays_3
Необходимо написать запрос, который выводит дату первого четверга августа года рождения клиента для всех клиентов в формате по умолчанию.
Насколько понимаю, ожидается использование функции strftime, но я что-то совсем в тупике(
Ответы (5 шт):
СУБД угадана как SQLite
select birthday, DATE(STRFTIME('%Y-08-01',birthday),'+' || ((10-STRFTIME('%w',datetime(STRFTIME('%Y-08-01',birthday))))%7+1) ||' days') as date from table1
birthday date
2023-07-07 2023-08-03
2022-05-02 2022-08-04
2015-04-03 2015-08-06
Самое простое это сначала определить какой день недели приходится на 1 августа и потом посмотреть сколько дне до четверга. Т.е. если 1 августа это понедельник, то четверг будет 4 августа.
По заданию, сначала нужно определить год - его можно получить из даты рождения клиента.:
YEAR(client_dob)
Потом надо собрать из получившегося года дату для первого августа
CONCAT(YEAR(client_dob), '-08-01')
Следующим шагом надо получить номер дня недели для этой даты
WEEKDAY(CONCAT(YEAR(client_dob), '-08-01'))
Функция WEEKDAY возвращает 0 для понедельника и 6 для воскресенья.
Дальше надо вычислить дату на которую приходится четверг. Подобранная опытным путем формула может быть такой ((3 - x) + 7) % 7 + 1 где x это день недели на которое попадает первое число. Если 1-ое число это четверг, то WEEKDAY вернет 3 и по формуле результат будет 1 - т.е. первое число. Если первое число это вторник (x = 1), то четверг будет третьим. По формуле получается 3. И возьмем случай когда 1-ое число это суббота (x = 5) и тогда первый четверг это 6-ое число. Считаем по формуле - получаем 6.
Если подставить выражение в формулу, то в результате будет вывод даты в интервале от 1 до 7.
(((3 - WEEKDAY(CONCAT(YEAR(client_dob), '-08-01'))) + 7) % 7 + 1)
А дальше осталось только собрать дату, зная год и число месяца
SELECT CONCAT(YEAR(client_dob), '-08-0', (((3 - WEEKDAY(CONCAT(YEAR(client_dob), '-08-01'))) + 7) % 7 + 1))
Короткое решение задачи
select DATE(STRFTIME('%Y-08-%d',(STRFTIME('%Y-08-01',BIRTH_DT)), 'weekday 4'))
Напишите запрос, который выводит дату первого четверга августа года рождения клиента для всех клиентов в формате по умолчанию. Удалите из выборки дубликаты и отсортируйте выборку по году. Например, 2022-05-22.
В выборке должен присутствовать один атрибут: date.
SELECT DISTINCT (
DATE (
STRFTIME('%Y-08-01', BIRTH_DT)
,'+' || ((10 - STRFTIME('%w',
DATETIME (STRFTIME('%Y-07-31', BIRTH_DT)))) % 7) || ' days'
)
) AS DATE
FROM dim_client
ORDER BY strftime('%Y', DATE (DATE)) ASC
select
--BIRTH_DT, --дата рождения
--STRFTIME('%Y-08-01',BIRTH_DT), --первое августа года рождения
--STRFTIME('%w',STRFTIME('%Y-08-01',BIRTH_DT)), --день недели первого августа года рождения
DISTINCT( --удаляем дубли
STRFTIME('%Y',BIRTH_DT)||'-08'||'-0'||CASE /* конкатинируем через дефис
год рождения август и значение дня первого четверга.
При этом дату первого четверга определяем исходя из условия */
WHEN STRFTIME('%w',STRFTIME('%Y-08-01',BIRTH_DT)) in ('3','2','1','4','0') /*
если день недели у 1.08 пределился как пн, вт, ср или чт */
THEN 1+(4- STRFTIME('%w',STRFTIME('%Y-08-01',BIRTH_DT))) /*
то чтобы получить день первого четверга, нужно добавить к 1.08
значение 3 (это четверг) минус получившийся день недели */
ELSE 1+(11- STRFTIME('%w',STRFTIME('%Y-08-01',BIRTH_DT))) /*
иначе, если день 1.08 пределился как пт, сб и вс,
то нужно добавить к 01.08 разницу до следующего четверга,
а именно (7+3=10) минуc получившееся значение */
END) as date
FROM ТАБЛИЦА
order by date -- сортируем по дате