[英]adding a many-to-many table relationship into this query
我有(相對於我有限的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)列表,該表通過鏈接表(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。 請注意,我需要能夠將許多類型標簽的結果加在一起。
如果用戶選擇genre:rock(genre_id:1),則應返回$ sTable中所有與genre_id:1相關聯的歌曲。 (以及我當前查詢檢索到的有關歌曲的其余信息。
但是...如果用戶選擇genre:rock(genre_id:1)AND genre:pop(genre_id:2)AND genenre:rap(genre_id:3),則應返回所有帶有這些標簽中任何一個的歌曲。
我很抱歉這是一個非常復雜的問題,我意識到我可能沒有很好地闡明它。 我也知道這都是我當前代碼所特有的。 無論如何,我真的希望有人能幫助我或至少朝正確的方向努力。
非常感謝!
編輯:
我只是想通過將以下代碼添加到我的查詢中來使他“接近”工作:
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行。 在歌曲/流派鏈接表中具有條目的每首歌曲都會被復制。
首先,就優化/最佳實踐而言,我當前的解決方案是一個好的解決方案嗎? 其次,如何防止這些重復的行?
注意:我已經在鏈接表的兩列中都有唯一的主鍵。
http://hackmysql.com/case4我認為這對您是一個很好的閱讀,特別是考慮到您的數據庫可能會到達大量的行。 在您的mysql表中使用索引鍵可以極大地加快查詢,其中一個表必須從另一表中繪制,或者一個表中有許多行,其中一列可能具有相似的值,而其他列則沒有。 至少就我所知,這使他們不必掃描整個表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.