2013-05-13 69 views
0

我需要做一組相當複雜的MySQL查詢來生成適合於從分配給不同音樂藝術家的標籤數據庫中繪製D3的數據。相關表中的行(稱爲「lastfm_annotations」)爲:user_id,artist_id,tag_id和tag_month(即,我們記錄了特定用戶在特定時間用特定標籤標記特定藝術家的許多實例)。這全部嵌入在php腳本中。在一個複雜的MySQL查詢中排序和分組

我最終需要生成的是一個JSON對象,該對象包含給定範圍內的日期內該特定藝術家在該月內使用的每個唯一標記的次數(包括日期爲零的計數。這是不使用給定的標籤

這是我迄今爲止(假設$ ITEMID和artist_id是可以互換位置):

$cal = array(); 
$result = mysql_query("select date from calendar;"); 
// this just gets all possible dates, but of course could be changed to get a different date range 
if (!$result) { 
    echo 'Could not run query: ' . mysql_error(); 
    exit; 
} 

for ($i = 0; $i < mysql_num_rows($result); $i++) { 
    $date =mysql_fetch_row($result)[0]; 
    $result2 = mysql_query("select t2.tag_id, case when t1.freq is null then 0 else t1.freq end as freq from (select distinct tag_id from lastfm_annotations where artist_id='" . $itemID . "') t2 left join (select tag_id, count(*) as freq from lastfm_annotations where artist_id='" . $itemID . "' and tag_month='" . $date . "' group by tag_id) as t1 on t2.tag_id = t1.tag_id group by t2.tag_id");  
    $current = array(); 
    $current['date'] = $date; 
    for ($j = 0; $j < mysql_num_rows($result2); $j++) { 
     $row = mysql_fetch_row($result2); 
     $tag = $row[0]; 
     $freq = $row[1]; 
     $result3 = mysql_query("select tag_name from lastfm_taglist where tag_id ='" . $tag . "' limit 1;"); 
     $tagName = mysql_fetch_row($result3)[0]; 
     $current[$tagName] = $freq; 
    } 
    array_push($data, $current); 
} 
echo json_encode($data); 

(編輯:大查詢如下)

select t2.tag_id 
    , case 
     when t1.freq is null then 0 
     else t1.freq 
     end as freq 
    from 
     (select distinct tag_id 
      from lastfm_annotations 
     where artist_id='$itemID') t2 
     left join 
     (select tag_id, count(*) as freq 
      from lastfm_annotations 
     where artist_id='$itemID' 
      and tag_month='$date' 
     group by tag_id) as t1 
     on t2.tag_id = t1.tag_id 
group by t2.tag_id 

(結束編輯)

這有效,但(至少)有兩個大問題,我無法弄清楚。首先,在大丑SQL查詢,我做多餘的工作我每次經過循環時調用

(select distinct tag_id from lastfm_annotations where artist_id='" . $itemID . "') 

,儘管該值每一次相同。任何想法我怎麼能解決這個問題?也許可以以某種方式將唯一tag_ids保存爲php數組,然後將其插入查詢中?

其次,我需要確保標籤始終按其總體頻率排序(即跨越所有時間,而不僅僅是在特定月份內),但我不知道如何做到這一點。我可以使用查詢像得到正確的順序:

但我需要確保我的循環每個查詢在相同的順序返回標籤。有任何想法嗎?當我真正開始繪製數據時,也許最好在d3中處理排序,但是如果數據在進行SQL調用時以正確的順序開始,那將會更好。

對不起,這個大問題,謝謝你的幫助!

+0

感謝您編輯Alanyst - 現在它更具可讀性。 – moustachio 2013-05-13 16:45:48

+0

備註:可以使用更簡潔的'ifnull(t1.freq,0)'代替查詢中t1.freq爲null,否則爲其他t1.freq end'的情況。 – Alanyst 2013-05-13 17:01:59

+0

如果藝術家A在特定的月份中使用了標籤'foo',但從未用於藝術家B,藝術家B的結果應該具有標記'foo'的行(具有'freq' == 0),或者應該B的結果只有用於B的標籤? – Alanyst 2013-05-13 17:18:14

回答

0

下面是一個針對每個藝術家而不是每個藝術家月份組合執行一次的查詢。它通過加入artist_id上的子查詢,然後在where子句中的artist_id = $itemID上進行過濾來解決您的第一個問題。數據庫引擎在處理查詢時應將條件壓入子查詢中,因此它不會像看起來那樣低效,並且由於它不在月循環中調用,所以它應該在整體上減少工作量。

第二個問題通過從第一個子查詢中獲取總體頻率並按該頻率按降序排列整個結果集來解決。這將首先放置標記最多的月份。

這樣做的缺點是沒有標籤的月份沒有在結果中顯示。您可以在應用程序邏輯中解決此問題(例如,通過跟蹤您的日期範圍中的哪些月份沒有出現在每個標記中,然後合成'0'行)。還應該可以擴展查詢以包含缺失的月份,但由於複雜性,除非您有興趣,否則我不會詳細討論。

select t1.tag_id 
    , t2.tag_month 
    , t2.freq as month_freq 
    , t1.freq as total_freq 
    from (select tag_id 
      , artist_id 
      , count(*) as freq 
      from lastfm_annotations 
     group by tag_id, artist_id) t1 
     inner join 
     (select tag_id 
      , tag_month 
      , artist_id 
      , count(*) as freq 
      from lastfm_annotations 
     group by tag_id, tag_month, artist_id) t2 
     on t1.artist_id = t2.artist_id and t1.tag_id = t2.tag_id 
where t2.tag_month between '$dateRangeStart' and '$dateRangeEnd' 
    and t1.artist_id = '$itemID' 
order by total_freq desc, t1.tag_id 
+0

這似乎很好地工作 - 謝謝!我做的唯一編輯也是通過tag_month命令,但這是一個非常微不足道的變化。我唯一關心的是執行時間......我用一個任意的藝術家ID來執行此操作,並且花了2小時的時間來生成結果......我的目標是將這部署在交互式可視化工具中,但這不是真的可能有那種執行時間。仍然接受,因爲它確實回答了我所有的問題。儘管如此,任何有關執行時間問題的想法都會受到讚賞。 – moustachio 2013-05-15 13:43:31

+0

桌上有什麼索引? – Alanyst 2013-05-15 17:22:08

+0

user_id + item_id + tag_id上的複合主鍵,以及item_id,artist_id,tag_id和tag_month上的(非唯一)索引。其中一些可能是多餘的,因爲我一直在調整數據庫結構一段時間。爲了澄清事情,每個項目(專輯,藝術家或歌曲)都有一個唯一的ID,但每個註釋(標記項目的實例)都有一個關聯的artist_id。下面是應該使事情更清晰的數據庫結構的屏幕截圖:[索引](https://dl.dropboxusercontent.com/u/625604/indexes.PNG),[表結構](https://dl.dropboxusercontent.com /u/625604/tableStructure.PNG)。 – moustachio 2013-05-15 19:23:50