簡體   English   中英

為一對多表實現查找或插入

[英]Implementing a find-or-insert for one-to-many tables

我有2個表, track tracklisttrack ,其中track tracklist有很多tracks 在某些時候,我將收到涉及軌道列表的用戶輸入,並且我需要創建該軌道列表或返回現有的軌道列表(這是因為軌道列表對用戶而言是完全透明的)。

我對此的幼稚解決方案是查找所有具有n軌道的track tracklist ,並針對tracklist n次,並根據用戶輸入數據檢查每個tracklist 例如,有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)

但是,這確實無法很好地擴展到大型曲目列表。 我最基本的時間表明,對於10個曲目跟蹤列表,此過程可能需要> 500毫秒,而對於具有100個曲目的跟蹤列表,此過程可能需要約7s。 盡管后者是一個極端的情況,但是我使用的任何算法都必須至少能夠擴展到這種程度。

但是,我仍然堅持使用其他解決方案。 我唯一想到的是選擇所有具有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()
);

有什么建議么?

  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'

由於我可能沒有完全正確的語法,也沒有機會對其進行測試,因此接下來是我要達到的目的的書面說明:

我建立一個查詢,返回您擁有的曲目列表。 建立完此查詢后,我將檢查這些軌道的軌道列表是否全部相同。 如果是,即查詢中只有一個跟蹤列表,則這是您需要的跟蹤列表。 如果查詢中沒有跟蹤列表,或者有多個跟蹤列表,那么您擁有的跟蹤集將不與任何單個現有跟蹤列表相對應,因此您需要創建一個新的跟蹤列表。 如果證明有必要,此查詢將不處理實際的創建。 我不確定它將如何處理退化的情況-查詢中根本沒有跟蹤; 或沒有列出任何曲目的曲目列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM