我需要执行一组相当复杂的 MySQL 查询,以从分配给不同音乐艺术家的标签数据库中生成适合在 D3 中绘制的数据。相关表(称为“lastfm_annotations”)中的行是:user_id、artist_id、tag_id 和 tag_month(即,我们记录了特定用户在特定时间用特定标签标记特定艺术家的许多实例)。这一切都嵌入在一个 php 脚本中。
最后我需要生成的是一个 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 数组,然后将其插入查询中?
其次,我需要确保标签总是按它们的整体频率排序(即在所有时间,而不仅仅是在特定月份内),但我不知道如何做到这一点。我可以使用类似的查询获得正确的序列:
select tag_id, count(*) as freq from lastfm_annotations where item_id=XXX order by freq desc
但我需要确保循环中的每个查询都以相同的顺序返回标签。有任何想法吗?也许在我实际开始绘制数据时处理 d3 中的排序会更好,但如果在我进行 SQL 调用时数据以正确的顺序开始会更好。
抱歉这个大问题,感谢您的帮助!