Реализация поиска или вставки для таблиц «один ко многим» - PullRequest
1 голос
/ 22 февраля 2011

У меня есть 2 таблицы, tracklist и track, где tracklist имеет много tracks. В некоторые моменты я получу пользовательский ввод, который ссылается на список треков, и мне нужно либо создать этот треклист, либо вернуть существующий треклист (это потому, что треклисты должны быть полностью прозрачными для пользователей).

Моим наивным решением было найти все треклисты с n треками и присоединиться к track против tracklist n раз, проверяя каждое объединение по введенным пользователем данным. Например, с 2 треками:

SELECT tracklist.id FROM tracklist
  JOIN track t1 ON tracklist.id = t1.tracklist
  JOIN track_name tn1 ON t1.name = tn1.id
  JOIN track t2 ON tracklist.id = t2.tracklist
  JOIN track_name tn2 ON t2.name = tn2.id
 WHERE tracklist.track_count = '20'
   AND (t1.position = 1 AND tn1.name = 'Pancakes' AND t1.artist_credit = '42' AND t1.recording = 1)
   AND (t2.position = 2 AND tn2.name = 'Waffles' AND t2.artist_credit = '9001' AND t2.recording = 2)

Однако, это действительно плохо масштабируется для больших треклистов. Мое очень элементарное время показывает, что это может занять> 500 мс для 10 треклистов и ~ 7 с для треклистов с 100 треками. В то время как последний является крайним случаем, любой алгоритм, который я использую, должен иметь возможность масштабироваться по крайней мере до этого.

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


Вот схема, с которой я работаю:

CREATE TABLE track
(
    id                  SERIAL,
    recording           INTEGER NOT NULL, -- references recording.id
    tracklist           INTEGER NOT NULL, -- references tracklist.id
    position            INTEGER NOT NULL,
    name                INTEGER NOT NULL, -- references track_name.id
    artist_credit       INTEGER NOT NULL, -- references artist_credit.id
    length              INTEGER CHECK (length IS NULL OR length > 0),
    edits_pending       INTEGER NOT NULL DEFAULT 0,
    last_updated        TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE TABLE track_name (
    id                  SERIAL,
    name                VARCHAR NOT NULL
);

CREATE TABLE tracklist
(
    id                  SERIAL,
    track_count         INTEGER NOT NULL DEFAULT 0,
    last_updated        TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

Есть предложения?

1 Ответ

1 голос
/ 22 февраля 2011
  SELECT DISTINCT tracklist
    FROM track t0
    WHERE 
      (SELECT COUNT(DISTINCT tracklist)
        FROM track t1
          WHERE 
            (
              (t1.id='test1.id')
              OR 
              (t1.id='test2.id')

              ......
              OR 
              (t1.id='testn.id')
            )
      = 1);

  -- This is OK if you have the track ids for this query.
  -- If you do not then you need to replace each of the t1.id='testm.id' statements
  -- with:
  --      t1.recording='testm.recording' AND
  --      t1.tracklist='testm.tracklist' AND
  --      t1.position='testm.position' AND
  --      t1.name='testm.name' AND
  --      t1.artist_credit='testm.artist_credit' AND
  --      t1.length='testm.length' AND
  --      t1.edits_pending='testm.edits_pending' AND
  --      t1.last_updated='testm.last_updated'

Поскольку у меня может быть неверный синтаксис, и у меня не было возможности проверить его, следующее письменное описание того, чего я пытаюсь достичь:

Я создаю запрос, возвращающий список треков, которые у вас есть. Создав этот запрос, я проверяю, все ли списки треков для этих треков одинаковы. Если они есть, то есть в запросе только один треклист, то этот треклист вам нужен. Если в запросе нет треклистов или их несколько, то набор треков, которые у вас есть, не соответствуют ни одному из существующих треклистов, поэтому вам нужно создать новый треклист. Этот запрос не касается реального создания, если это окажется необходимым. Я не уверен, как это будет иметь дело с вырожденными случаями - в запросе нет никаких следов; или в списке треков нет ни одного трека.

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