2013-05-13 116 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