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

Демо

→ Ссылка
Автор решения: Vladimir Ignatenko

Самое простое это сначала определить какой день недели приходится на 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))
→ Ссылка
Автор решения: user578406

Короткое решение задачи

select DATE(STRFTIME('%Y-08-%d',(STRFTIME('%Y-08-01',BIRTH_DT)), 'weekday 4'))
→ Ссылка
Автор решения: user611098

Напишите запрос, который выводит дату первого четверга августа года рождения клиента для всех клиентов в формате по умолчанию. Удалите из выборки дубликаты и отсортируйте выборку по году. Например, 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 -- сортируем по дате
→ Ссылка