Как бороться с нестандартными форматами даты в SQL (mySQL)? - PullRequest
1 голос
/ 26 сентября 2019

Я новичок в SQL и учусь на данный момент.Я использую MySQL, установленный в Ubuntu 18.04.

У меня есть следующая таблица:

CREATE TABLE IF NOT EXISTS product(name varchar(255) NOT NULL, 
                                   availability date NOT NULL);

Я хочу вставить следующую запись в таблицу:

INSERT INTO `product` (`name`, `availability`) 
VALUES ('Title 1', last Wednesday);

при выполнении я получаю следующую ошибку:

ОШИБКА 1064 (42000) в строке 21: у вас есть ошибка в вашем синтаксисе SQL;проверьте руководство, соответствующее вашей версии сервера MySQL, на предмет правильного синтаксиса, который нужно использовать около «среды»

Я понимаю, что этот формат («последняя среда», «следующая неделя», ..)не стандартный формат даты.Я хотел знать, возможно ли создание пользовательских типов в MySQL, чтобы иметь возможность обрабатывать эти записи даты на заказ.

До сих пор то, что я обнаружил в Интернете, касается дат, которые все еще содержат более или менее стандартный формат даты, не такой заказной, как упомянутые выше (используйте cast, parse, ..).

Ответы [ 4 ]

2 голосов
/ 26 сентября 2019

Имеются такие функции, как NOW(), CURRENT_TIMESTAMP() и CURRENT_DATE().Для чего-либо еще, например LAST_WEDNESDAY(), вы можете написать свои собственные хранимые функции .

create function last_wednesday() returns date no sql
  return current_date() - interval (weekday(current_date()) + 4)%7+1 day;

или использовать то же выражение, встроенное в ваши запросы.

Update

По просьбе Strawberry - вот что-то «более масштабируемое»:

create function human_to_date(str text, date date) returns date no sql
  return case
    when str = 'last monday'    then date - interval (weekday(date) + 6-0)%7+1 day
    when str = 'last tuesday'   then date - interval (weekday(date) + 6-1)%7+1 day
    when str = 'last wednesday' then date - interval (weekday(date) + 6-2)%7+1 day
    when str = 'last thursday'  then date - interval (weekday(date) + 6-3)%7+1 day
    when str = 'last friday'    then date - interval (weekday(date) + 6-4)%7+1 day
    when str = 'last saturday'  then date - interval (weekday(date) + 6-5)%7+1 day
    when str = 'last sunday'    then date - interval (weekday(date) + 6-6)%7+1 day
  end
;

Используйте его как

select human_to_date('last wednesday', now())

или для любой даты в качестве ссылки

select human_to_date('last sunday', '2019-10-01')

Это вернет последнее воскресенье в этом месяце (сентябрь 2019)

См. demo

Я пытался удалить дублирование кода, но закончил так:

delimiter //
create function human_to_date(str text, date date) returns date no sql
begin
  declare day_of_week int default null;
  if str rlike '^last (monday|tuesday|wednesday|thursday|friday|saturday|sunday)$' then
    set day_of_week = case substring_index(str, ' ', -1)
      when 'monday'    then 0
      when 'tuesday'   then 1
      when 'wednesday' then 2
      when 'thursday'  then 3
      when 'friday'    then 4
      when 'saturday'  then 5
      when 'sunday'    then 6
    end;
    return date - interval (weekday(date) + 6-day_of_week)%7+1 day;
  end if;
  return null;
end //
delimiter ;

db-fiddle

1 голос
/ 26 сентября 2019

Когда дело доходит до дат, возможности некоторых языков приложений на естественном языке настолько хороши, что вместо этого у меня возникает соблазн обработать логику.

Например, вот какой-то PHP:

<?php

echo(date(DATE_RFC850,strtotime( date('Y-m-01', strtotime('next month')).' last wednesday')));

?>

Сегодня четверг, 26 сентября.Это повторяет среду, 25 сентября 19:00:00 BST

0 голосов
/ 26 сентября 2019

Вот код для вставки даты последней среды в вашу таблицу:

INSERT INTO product(name, availability)
SELECT
    'Title 1',
    CASE WHEN WEEKDAY(CURDATE()) >= 2
         THEN TIMESTAMPADD(DAY, 2 - WEEKDAY(CURDATE()), CURDATE())
         ELSE TIMESTAMPADD(DAY, 2 - WEEKDAY(CURDATE()) - 7, CURDATE()) END;

Примечания: было бы трудно осуществить это, используя предложение select с предложением VALUES, если только мы не определяем UDFпоэтому я использую INSERT INTO ... SELECT.Выражение CASE проверяет, является ли текущая дата средой (2) - воскресеньем (6).Если это так, то мы смещаем текущую дату на разницу, чтобы перевести ее обратно в среду.Аналогичная логика применяется к понедельнику (0) и вторнику (1).

0 голосов
/ 26 сентября 2019

При хранении в БД вам нужна информация, которая имеет смысл.значение "последняя среда" для продукта не дает никакой разумной информации о доступности.Например, в прошлую среду с какой даты?Если кто-то запросит все доступные продукты в прошлую среду, но на 2 месяца позже, чем сегодня, что вернет запрос, ищущий «в прошлую среду»?Определенно неверные результаты.Итак, если вы хотите сохранить дату, используйте тип данных date / datetime.Вы можете добавить любое произвольное описание, которое хотите, используя дополнительный столбец с типом данных varchar, но я бы не стал использовать его в качестве основного источника информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...