Postgresql форматирование даты - PullRequest
0 голосов
/ 28 января 2012

У меня есть набор данных (в формате .tsv), где одним из столбцов является дата рождения . Однако данные устарели, и не все даты имеют формат YYYY-MM-DD. У некоторых записей есть только год рождения (месяц и день рождения отсутствуют) и они имеют формат YYYY-##-## (буквально ## уже введены в данные везде, где известен только год). Я хочу загрузить этот набор данных в мою базу данных postgres со столбцом дата рождения с типом данных date, а не string, чтобы можно было сравнивать даты .
Небольшой образец показан ниже. (Неактуальные столбцы данных не отображаются)

1924-##-##
1965-09-04
1944-11-05
1951-##-##
-388-##-##
1893-01-26
1037-##-##

Непосредственная массовая загрузка набора данных очевидно, выдает ошибку

ERROR:  invalid input syntax for type date: "1924-##-##"
LINE 1: insert into d values ('1924-##-##');
                              ^

Набор данных довольно большой, имеет около 6 крор записей. В настоящее время я планирую запустить скрипт для замены этих ## на 01 и затем вставить измененные данные в базу данных. Но мне не нравится эта идея для -

  1. Это отнимает много времени.
  2. Это занимает много места на диске (как я хотел бы сохранить исходные "нетронутые" данные)
  3. Кроме того, не все мои данные будут подлинными в моей базе данных.

Можно ли как-нибудь попросить postgres как-то просто взять даты такими, какие они есть, просто игнорируя символы ## (и просто сохраняя год, в котором пропущены месяцы и дни)?
Или может быть лучшее решение этой проблемы?

Ответы [ 3 ]

1 голос
/ 29 января 2012

Вы можете создать в своей таблице два столбца, один для первоначально введенного значения (тип varchar) и один для расчета (тип date).

CREATE TABLE your_table
(
 id INT,
 -- OTHER DETAILS
 dob_entered    VARCHAR,
 dob_parsed DATE
);

Затем вы можете использовать триггер Insert для автоматического заполнения поля даты из varchar с помощью триггера обновления для обработки любых изменений.

CREATE OR REPLACE FUNCTION evaluate_dob_date() RETURNS TRIGGER AS
$$
BEGIN
    NEW.dob_parsed = CAST(REPLACE(NEW.dob_entered,'##','01') AS DATE);
    RETURN new;
END;
$$
LANGUAGE plpgsql;

CREATE TRIGGER parse_dob 
BEFORE INSERT OR UPDATE ON your_table
FOR EACH ROW
EXECUTE PROCEDURE evaluate_dob_date();

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

Триггеры Postgresql

0 голосов
/ 28 января 2012

Если вам нужно сохранить символы #, единственный шанс, который я вижу, это импортировать их в столбец varchar.

Если вам абсолютно необходима информация в качестве даты, вам может не понравиться представление, которое выполняет преобразование и выбирает только те строки, в которых в столбце нет #.

Что-то вроде

SELECT to_date(dob,'YYYY-MM-DD') as dob_date
FROM your_table
WHERE substr(dob,6,2) <> '##';

Если вы делаете это на регулярной основе, вы можете рассмотреть индекс для этого выражения, чтобы ускорить выбор:

CREATE INDEX dob_check ON your_table( substr(dob,6,2) );

Обратите внимание, что выражение в вашем выборе должно совпадать с точно выражением в индексе, чтобы его можно было использовать в планировщике запросов.

Если вы хотите «преобразовать» данные в действительную дату во время поиска, вы можете сделать что-то вроде этого:

SELECT case 
         case when substr(dob,6,2) = '##' then to_date(substr(dob,1,5)||'01-01', 'YYYY-MM-DD')
         else to_date(dob,'YYYY-MM-DD')
       end as dob_date
FROM your_table;
0 голосов
/ 28 января 2012

У вас есть два варианта здесь

  1. После извлечения данных из базы данных замените все вхождения # в сценарии на стороне сервера, а затем сравните даты. (Вы также можете заменить данные динамически в самой таблице, не изменяя существующие данные, используя условие if в запросе)
  2. Игнорировать даты, которые имеют #. Таким образом, вы можете сравнить только действительные даты.
...