如何在此SQL查询中返回SUM(摘要)

时间:2012-03-01 20:08:47

标签: php mysql sql

我想通过随机从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");
    }

有可能吗?我试过了,但它没有用。

3 个答案:

答案 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++;
    } 
}