2011-10-28 64 views
0

我有一個表標籤與字段tag_idname。我有一個連接表tag_map與字段tag_idvid_id連接表標籤到表視頻(通過vid_id)。防止ghost條目在很多到很多

當我插入一個新的標籤爲vid_id,刪除我在tag_map所有條目爲vid_id,如果有在tag_map只有一個條目我也想刪除標籤表tags防止鬼項(標籤項沒有相應的tag_map條目)。

問題是,我似乎無法準確獲得此計數。例如,如果我在tag_map中有3個條目,每個條目在tags中有1個相應的標籤,則每個標籤的計數爲1,0,0。我爲此使用了錯誤的查詢嗎?

//find all tags for given vid_id 
$sql = 'SELECT tag_map.*, tags2.name AS tag_name 
FROM tag_map 
INNER JOIN tags2 ON tags2.tag_id = tag_map.tag_id 
INNER JOIN video ON video.vid_id = tag_map.vid_id 
WHERE tag_map.vid_id=?'; 
$stmt_tags = $conn->prepare($sql); 
$result=$stmt_tags->execute(array($vid_id)); 

while ($row = $stmt_tags->fetch(PDO::FETCH_ASSOC)) { 
$tag_name=$row['tag_name']; 

//for each tag check how many rows exist in tag_map COUNT IS NOT ACCURATE 
    $sql = 'SELECT *, COUNT(tags2.name) as cnt 
FROM tag_map 
JOIN tags2 ON tags2.tag_id = tag_map.tag_id 
JOIN video ON video.vid_id = tag_map.vid_id 
WHERE tags2.name=?'; 
$stmt_tags2 = $conn->prepare($sql); 
$result=$stmt_tags2->execute(array($tag_name)); 

while ($row2 = $stmt_tags2->fetch(PDO::FETCH_ASSOC)) { 
    echo $cnt=$row2['cnt']; 
} 

if ($cnt==1){ 
    $sql = "DELETE FROM tag_map WHERE vid_id = ?"; 
$stmt14 = $conn->prepare($sql); 
$result=$stmt14->execute(array($vid_id)); 
    $sql = "DELETE FROM tags2 WHERE tags2.name = ?"; 
$stmt14 = $conn->prepare($sql); 
$result=$stmt14->execute(array($tag_name)); 
} 
else { 
     $sql = "DELETE FROM tag_map WHERE vid_id = ?"; 
$stmt14 = $conn->prepare($sql); 
$result=$stmt14->execute(array($vid_id)); 
} 
} 

編輯插入到多對多

foreach($variable as $tag) { 

    $sql = 'SELECT *, COUNT(tags2.name) as cnt 
FROM tag_map 
JOIN tags2 ON tags2.tag_id = tag_map.tag_id 
JOIN video ON video.vid_id = tag_map.vid_id 
WHERE tags2.name=?'; 
$stmt_tags2 = $conn->prepare($sql); 
$result=$stmt_tags2->execute(array($tag)); 
while ($row = $stmt_tags2->fetch(PDO::FETCH_ASSOC)) { 
    $cnt=$row['cnt']; 
    $exist_tag_id=$row['tag_id']; 
} 

$id=md5(uniqid()); 
$tag_id=md5(uniqid()); 

if ($cnt==0){ 
    $sql="INSERT into tag_map (id,vid_id,tag_id) VALUES (?,?,?)"; 
$stmt16 = $conn->prepare($sql); 
$result=$stmt16->execute(array($id,$vid_id,$tag_id)); 
    $sql="INSERT into tags2 (tag_id,name) VALUES (?,?)"; 
$stmt16 = $conn->prepare($sql); 
$result=$stmt16->execute(array($tag_id,trim($tag))); 
} 
else { 
$sql="INSERT into tag_map (id,vid_id,tag_id) VALUES (?,?,?)"; 
$stmt16 = $conn->prepare($sql); 
$result=$stmt16->execute(array($id,$vid_id,$exist_tag_id)); 
} 

} 

回答

1

你真的甚至不需要擔心計數。從tag_map刪除然後:

DELETE t 
    FROM tags2 t 
     LEFT JOIN tag_map tm 
      ON t.tag_id = tm.tag_id 
    WHERE tm.tag_id IS NULL; 
+0

非常感謝喬,這比我的效率高得多。我編輯了我的問題,以顯示如何在標籤被移除後插入標籤。計數是否需要插入? – Scarface

+0

@Scarface:如果你已經在這些表之間創建了合適的外鍵關係(如果你沒有,現在就這樣做,稍後你會感謝我),那麼你的第一次插入會失敗,因爲你不能插入' tag_map'直到所有標籤首先存在於tags2中。 –

+0

再次感謝Joe,我肯定會研究外鍵,並將其添加到我的關係中。但是,如何在不首先查詢'tags2'來檢查現有標籤的tag_id的情況下如何將'tag_map' tag_id連接到'tags2' tag_id? – Scarface

1

難道你不能這樣做嗎?或者我錯過了什麼?

刪除某個視頻中的所有標籤,然後刪除tag_map表中沒有對應值的標籤。

DELETE FROM tag_map WHERE vid_id = <video_id>; 
DELETE FROM tags t 
WHERE NOT EXISTS (SELECT 1 FROM tag_map tm WHERE tm.tag_id = t.tag_id); 
+0

感謝您的建議美穗。 – Scarface

1

在這兩個查詢中,由於您只在vid_id上操作,因此不需要加入視頻。只需專注於tags2和tag_map表。通過額外連接,如果您沒有該標記的視頻條目,則可能會得到一個假0。

另外,如果你想獲得一個計數特定TAG_ID,請執行下列操作:

SELECT COUNT(tm.tag_id) FROM tags2 t 
    LEFT OUTER JOIN tag_map ON tm.tag_id = t.tag_id 
    WHERE t.name = ? 

執行外連接,這樣你就會得到0計數那裏沒有一個條目在標籤的tag_map中。

但是,我更喜歡一個實際的DELETE,就像上面檢查存在的DELETE一樣。

+0

我甚至沒有想到這一點,非常感謝克里斯。這個答案對我來說非常有幫助。 – Scarface