2016-05-06 4 views
1

Я пытаюсь создать базу данных для movielens (http://grouplens.org/datasets/movielens/). У нас есть фильмы и рейтинги. Фильмы имеют несколько жанров. Я разделил их на отдельный стол, так как это соотношение 1: много. Есть много: много отношений, а также пользователей фильмов. Мне нужно иметь возможность запрашивать эту таблицу несколькими способами.Данные CSV-файла в таблицу PostgreSQL

Так что я создал:

CREATE TABLE genre (
    genre_id serial NOT NULL, 
    genre_name char(20) DEFAULT NULL, 
    PRIMARY KEY (genre_id) 
) 

.

INSERT INTO genre VALUES 
    (1,'Action'),(2,'Adventure'),(3,'Animation'),(4,'Children\s'),(5,'Comedy'),(6,'Crime'), 
    (7,'Documentary'),(8,'Drama'),(9,'Fantasy'),(10,'Film-Noir'),(11,'Horror'),(12,'Musical'), 
    (13,'Mystery'),(14,'Romance'),(15,'Sci-Fi'),(16,'Thriller'),(17,'War'),(18,'Western'); 

.

CREATE TABLE movie (
    movie_id int NOT NULL DEFAULT '0', 
    movie_name char(75) DEFAULT NULL, 
    movie_year smallint DEFAULT NULL, 
    PRIMARY KEY (movie_id) 
); 

.

CREATE TABLE moviegenre (
    movie_id int NOT NULL DEFAULT '0', 
    genre_id tinyint NOT NULL DEFAULT '0', 
    PRIMARY KEY (movie_id, genre_id) 
); 

Я не знаю, как импортировать мой movies.csv с колоннами movie_id, MOVIE_NAME и movie_genre Например, первая строка (1;Toy Story (1995);Animation|Children's|Comedy) Если я ввожу вручную, он должен быть выглядеть следующим образом:

INSERT INTO moviegenre VALUES (1,3),(1,4),(1,5) 

Потому что 3 - это анимация, 4 - это дети и 5 - комедия

Как я могу импортировать все данные, установленные таким образом?

+0

Как вы загружаете свои данные с помощью COPY? Или вы редактируете текстовые файлы? –

+0

Я закачаю мои данные COPY – KTBFFH

ответ

1

Вы должны сначала создать таблицу, которая может глотать данные из файла CSV:

CREATE TABLE movies_csv (
    movie_id integer, 
    movie_name varchar, 
    movie_genre varchar 
); 

Обратите внимание, что любые одиночные кавычки (Children's) должна быть в два раза (Children''s). После того как данные в этой промежуточной таблице можно копировать данные через к movie таблице, которая должна иметь следующую структуру:

CREATE TABLE movie (
    movie_id integer, -- A primary key has implicit NOT NULL and should not have default 
    movie_name varchar NOT NULL, -- Movie should have a name, varchar more flexible 
    movie_year integer,   -- Regular integer is more efficient 
    PRIMARY KEY (movie_id) 
); 

Санируйте ваши другие таблицы также.

Теперь скопируйте данные через, извлекая неукрашенное имя и год от имени CSV:

INSERT INTO movie (movie_id, movie_name) 
    SELECT parts[1], parts[2]::integer 
    FROM movies_csv, regexp_matches(movie_name, '([[:ascii:]]*)\s\(([\d]*)\)$') p(parts) 

Здесь regular expression говорит:

  • ([[:ascii:]]*) - не захватить все символы до матчей ниже
  • \s - Прочитано пробел
  • \( - Прочитано прошлый открытие скобка
  • ([\d]*) - Захват любые цифры
  • \) - прочитать прошлое закрывающей скобкой
  • $ - Матч с конца строки

Так что на входе «Die Hard 17 (Джон живет вечно) (2074) «он создает строковый массив с {'Die Hard 17 (John lives forever)', '2074'}.Сканирование должно быть с конца $, предполагая, что все названия фильмов заканчиваются годом публикации в круглых скобках, чтобы сохранить круглые скобки и номера в названиях фильмов.

Теперь вы можете работать над жанрами фильмов. Вы должны разбить строку на панели |, используя функцию regex_split_to_table(), а затем присоединиться к genre таблице по названию жанра:

INSERT INTO moviegenre 
    SELECT movie_id, genre_id 
    FROM movies_csv, regexp_split_to_table(movie_genre, '\|') p(genre) -- escape the | 
    JOIN genre ON genre.genre_name = p.genre; 

После все сделано и посыпанного вы можете удалить movies_csv таблицы.

+0

Отличное объяснение! Спасибо огромное! – KTBFFH

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