2012-01-26 182 views
1

我有什麼(用我有限的MYSQL知識)是一個比較複雜的查詢:加入了許多一對多表關係到這個查詢

$sQuery = " 
     SELECT SQL_CALC_FOUND_ROWS 
    songsID, song_name, artist_band_name, author, song_artwork, song_file, 
    song_description, uploaded_time, emotion, tempo, 
    user, happiness, instruments, similar_artists, play_count, 
    projects_count, 
    rating, ratings_count, waveform, datasize, display_name, user_url, 
    IF(user_ratings_count, 'User Voted', 'Not Voted') as voted 
FROM (
     SELECT 
      sp.songsID, projects_count, 
      AVG(rating) as rating, 
      COUNT(rating) AS ratings_count, 
      COUNT(IF(userid=$userid, 1, NULL)) as user_ratings_count 

       FROM (
        SELECT songsID, COUNT(*) as projects_count 
        FROM $sTable s 
        LEFT JOIN $sTable2 p ON s.songsID = p.songs_id 

        GROUP BY songsID) as sp 

      LEFT JOIN $sTable3 r ON sp.songsID = r.songid 

      GROUP BY sp.songsID) as spr 


JOIN $sTable s USING (songsID) 
LEFT JOIN $sTable5 q ON s.user = q.ID 


     $sWhere 
     $sOrder 
     $sLimit 

此查詢獲取所有關於5特定​​歌曲的信息不同的表格。

變量$ sWhere構建查詢的WHERE部分,並依賴於發送到服務器的數據,以便根據用戶輸入動態過濾該歌曲列表。

$ sOrder和$ sLimit命令並根據用戶輸入再次限制結果。

我現在需要在這個包含流派列表(wp_genres)的公式中添加第6個表格,該表格通過具有以下結構的鏈接表(wp_song_genres)鏈接到$ sTable中的songsID列: -

$sTable(wp_songs) $sTable6(wp_genre_songs)  $sTable7(wp_genres) 
songsID*    song_id*      genre_id** 
column2    genre_id**     genre_name 
column3           icon_url 
column4 
column5 
etc... 

星號表示鏈接。

我需要做的是讓我對歌曲結果的動態過濾器能夠按流派篩選歌曲列表,但我無法弄清楚如何引入新表格($ sTable6和$ sTable7)到查詢中。

下面是代碼生成我查詢的WHERE部分:

這部分需要通過「SSEARCH」收到的文本和搜索欄找到任何匹配的文本。

$sWhere = ""; 
if ($_GET['sSearch'] != "") 
{ 
    $aWords = preg_split('/\s+/', $_GET['sSearch']); 
    $sWhere = "WHERE ("; 

    for ($j=0 ; $j<count($aWords) ; $j++) 
    { 
     if ($aWords[$j] != "") 
     { 
      $sWhere .= "("; 
      for ($i=0 ; $i<count($aColumns) ; $i++) 
      { 
       $sWhere .= $aColumns[$i]." LIKE '%".mysql_real_escape_string($aWords[$j])."%' OR "; 
      } 
      $sWhere = substr_replace($sWhere, "", -3); 
      $sWhere .= ") AND "; 
     } 
    } 
    $sWhere = substr_replace($sWhere, "", -4); 
    $sWhere .= ')'; 
} 

這部分是一個「範圍」過濾器,使得用戶能夠輸入的最小速度值和最大速度值(通過一個jquery範圍滑塊完成上的字體端)。數據通過sSearch_ *接收。

/* Individual column filtering */ 
for ($i=0 ; $i<count($aColumns) ; $i++) 
{ 
    if ($_GET['bSearchable_'.$i] == "true" && $_GET['sSearch_'.$i] != '') 
    { 
     if ($sWhere == "") 
     { 
      $sWhere = "WHERE "; 
     } 
     else 
     { 
      $sWhere .= " AND "; 
     } 







     $columnFilterValue = mysql_real_escape_string($_GET['sSearch_' . $i]); 
     // check for values range 
     $rangeSeparator = "~"; 
     if (!empty($rangeSeparator) && strstr($columnFilterValue, $rangeSeparator)) { 
      // get min and max 

      $columnFilterRangeMatches = explode('~', $columnFilterValue); 

      // get filter 
      if (empty($columnFilterRangeMatches[0]) && empty($columnFilterRangeMatches[1])) 
       $sWhere .= " 0 = 0 "; 
      else if (!empty($columnFilterRangeMatches[0]) && !empty($columnFilterRangeMatches[1])) 
       $sWhere .= $aColumns[$i] . " BETWEEN '" . $columnFilterRangeMatches[0] . "' and '" . $columnFilterRangeMatches[1] . "' "; 
      else if (empty($columnFilterRangeMatches[0]) && !empty($columnFilterRangeMatches[1])) 
       $sWhere .= $aColumns[$i] . " < '" . $columnFilterRangeMatches[1] . "' "; 
      else if (!empty($columnFilterRangeMatches[0]) && empty($columnFilterRangeMatches[1])) 
       $sWhere .= $aColumns[$i] . " > '" . $columnFilterRangeMatches[0] . "' "; 
     } else { 
      $sWhere .= $aColumns[$i] . " LIKE '%" . $columnFilterValue . "%' "; 
     } 
    } 
} 

genre_id的數據將通過sSearch_23進入。即$ _GET ['sSearch']將包含我希望通過篩選結果的genre_id。請注意,我需要能夠將多個流派標籤的結果一起添加。

如果用戶選擇風格:rock(genre_id:1),那麼應該返回與$ sTable有關的genre_id:1的所有歌曲。 (約歌曲其餘的信息一起作爲retrievedby

但是...如果用戶選擇流派我當前查詢:巖(genre_id:1)和類型:流行(genre_id:2)和genenre:說唱。 (genre_id:3),那麼所有帶有這些標籤的歌曲都應該被退回。不管我真的希望有人能幫助我,或者至少讓我朝着正確的方向前進

非常感謝!

編輯:

我剛纔anaged通過將folling到我的查詢來獲取他的「近」工作:

LEFT JOIN (
      SELECT igs.song_id, igs.genre_id, g.genre_name 
      FROM $sTable6 AS igs 
      JOIN wp_genres AS g 
      ON igs.genre_id = g.genre_id 
      ) as gs 
      ON songsID = gs.song_id   

所以,整個事情現在看起來像: -

$sQuery = " 
     SELECT SQL_CALC_FOUND_ROWS 
    songsID, song_name, artist_band_name, author, song_artwork, song_file, 
    genre, song_description, uploaded_time, emotion, tempo, 
    user, happiness, instruments, similar_artists, play_count, 
    projects_count, 
    rating, ratings_count, waveform, datasize, display_name, user_url, genre_id, 
    IF(user_ratings_count, 'User Voted', 'Not Voted') as voted 
FROM (
     SELECT 
      sp.songsID, projects_count, 
      AVG(rating) as rating, 
      COUNT(rating) AS ratings_count, 
      COUNT(IF(userid=$userid, 1, NULL)) as user_ratings_count 

       FROM (
        SELECT songsID, COUNT(*) as projects_count 
        FROM $sTable s 
        LEFT JOIN $sTable2 p ON s.songsID = p.songs_id 

        GROUP BY songsID) as sp 

      LEFT JOIN $sTable3 r ON sp.songsID = r.songid 





      GROUP BY sp.songsID) as spr 

LEFT JOIN (
      SELECT igs.song_id, igs.genre_id, g.genre_name 
      FROM $sTable6 AS igs 
      JOIN wp_genres AS g 
      ON igs.genre_id = g.genre_id 
      ) as gs 
      ON songsID = gs.song_id   



JOIN $sTable s USING (songsID) 
LEFT JOIN $sTable5 q ON s.user = q.ID 





     $sWhere 
     $sOrder 
     $sLimit 

genre_id的查詢現在按預期發生完美和動態。但是,如果在查詢的WHERE部分中未指定genre_id,則會得到dupilcate行。歌曲/流派鏈接表中有條目的每首歌都會被複制。

首先,我的當前解決方案在優化/最佳實踐方面是否合適?其次,我怎樣才能防止這些重複的行?

注意:我已經在鏈接表中的兩列之間有一個唯一的主鍵。

回答

1

http://hackmysql.com/case4 我認爲這可以作爲一個很好的閱讀給你,特別是考慮到你的數據庫可能會達到大量的行。在你的mysql表中使用索引鍵可以大大加快查詢,其中一個表必須從另一個表中繪製,或者一個表中有許多行可能在一列中具有相似的值,但其他行中沒有。這使他們不必掃描整個桌子,至少據我所知。

+0

看起來像一個夢幻般的閱讀,我非常感謝您花時間發佈它。這將非常有用。它不回答我的問題,但非常感謝。乾杯! :-) – gordyr