我想通过随机从sql查询中直接获取SUM,但是如何从此查询返回duration字段的总和: 那是表:
CREATE TABLE IF NOT EXISTS `video_clips` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(155) NOT NULL,
`duration` int(11) NOT NULL,
`rank` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
INSERT INTO `video_clips` (`id`, `name`, `duration`, `rank`) VALUES
(1, 'clip1', 3, 1),
(2, 'clip2', 5, '3'),
(3, 'clip3', 8, '2'),
(4, 'clip4', 6, '1');
这就是代码:
$time=16;
while($sum=$time) {
$result=mysql_query("(SELECT duration FROM table where rank=1 ORDER BY rand() LIMIT 1) UNION ALL
(SELECT duration FROM table where rank=2 ORDER BY rand() LIMIT 1) UNION ALL
(SELECT duration FROM table where rank=3 ORDER BY rand() LIMIT 1)" );
$sum=??????
}
或者可以将结果添加到别名表中,然后从这个别名表中返回SUM:
$time=16;
while($sum=$time) {
$result=mysql_query("(SELECT duration FROM table where rank=1 ORDER BY rand() LIMIT 1) UNION ALL
(SELECT duration FROM table where rank=2 ORDER BY rand() LIMIT 1) UNION ALL
(SELECT duration FROM table where rank=3 ORDER BY rand() LIMIT 1) AS table1");
$sum=mysql_query("SELECT SUM(duration) FROM table1");
}
有可能吗?我试过了,但它没有用。
答案 0 :(得分:2)
就像@Dagon在评论中暗示的那样:
SELECT rank, SUM(duration)
FROM video_clips
GROUP BY rank WITH ROLLUP
这会给你这个结果:
+------+---------------+
| rank | SUM(duration) |
+------+---------------+
| 1 | 9 |
| 2 | 8 |
| 3 | 5 |
| NULL | 22 |
+------+---------------+
按列(rank)分组的NULL表示该行是a是“超级总计”。 更复杂的分组是可能的,有关详细信息,请参阅:
http://dev.mysql.com/doc/refman/5.5/en/group-by-modifiers.html
答案 1 :(得分:0)
不应该这样吗?
SELECT (SELECT duration FROM table where rank=1 ORDER BY rand() LIMIT 1)
+ (SELECT duration FROM table where rank=2 ORDER BY rand() LIMIT 1)
+ (SELECT duration FROM table where rank=3 ORDER BY rand() LIMIT 1)
AS sum;
答案 2 :(得分:0)
@Aram,问题是你要搜索一个特定的总数。但是,在你能够做到这一点之前,你必须在排除持续时间之前,按照等级制作所有可能的视频合格组合。
这不是您可以在大型RDBMS中有效执行的查询。
您可以做的是提前计算剪辑的平均持续时间(所需的持续时间/剪辑数量),并用于为查询创建额外条件,以便仅查找特定持续时间范围内的剪辑。但这还不够:我的假设是你还需要避免多次选择同一个片段。
虽然可以在单个查询中执行此操作,但我的建议现在是在PHP代码中以程序方式解决此问题。
//find the min and max id of clips to set up efficient random row selection:
$sql = 'SELECT min(id) min_id, max(id) max_id FROM video_clips';
$res = mysql_query($sql, $connection);
$min_max = mysql_fetch_assoc($res);
$min = $min_max['min_id'];
$max = $min_max['max_id'];
//vars to hold the user preferences
$target_dur = $_GET['desired_duration'];
$count_clips_per_rank = array(
1 => intval($_GET['count_rank1_clips'])
, 2 => intval($_GET['count_rank2_clips'])
, 3 => intval($_GET['count_rank3_clips'])
);
$total_count = array_sum($count_clips_per_rank);
//vars to keep track of the clip selection so far.
$actual_dur = 0;
$actual_count = 0;
$selection = array();
$selected_ids = '';
//query backbone
$base_sql = 'SELECT id, duration FROM video_clips WHERE rank = ';
//visit all desired ranks
for ($rank = 1; $rank <= 3; $rank++) {
//add a rank condition to find only clips of the desired rank
$sql = $base_sql.$rank;
//find the desired number of clips for this rank
$n = $count_clips_per_rank[$rank];
for ($i = 0; $i < $n; $i++) {
//establish a duration range (taking into account the selection so far)
//we arbitrarily choose a range of +/- 5%
$avg_dur = ($target_dur - $actual_dur) / ($total_count - $actual_count);
$range = $avg_dur * 0.05;
//add a condition to find only clips within the desired range
$sql .= ' AND duration BETWEEN '
. ($avg_dur - $range)
. ' AND '
. ($avg_dur + $range)
;
//add a condition to the query to exclude clips we found so far.
if ($selected_ids !== '') {
$sql .= $selected_ids.')'
}
//add a condition to the query to select a random clip
$rand = rand($min_id, $max_id);
$sql .= ' AND id > '.$rand.' LIMIT 1';
//find a clip
$res = mysql_query($sql, $connection);
$clip = mysql_fetch_assoc($res);
if ($clip === FALSE) {
//oops, no match found.
...intelligent code to deal with this error goes here...
}
//from here on, we assume we actually found a clip
//update the selection with the newly found clip
array_push($selection, $clip);
//do bookkeeping for the next iterations.
if ($selected_ids == '') {
$selected_ids = ' AND id NOT IN (';
}
else {
$selected_ids .= ',';
}
$selected_ids .= $clip['id'];
$actual_dur .= $clip['duration'];
$actual_count++;
}
}