如何通过查询分组使用distinct?

时间:2014-01-16 11:17:14

标签: mysql sql

我有这个查询

SELECT 
    user_id, 
    played_level, 
    sum( time_taken ) AS time_take
FROM answer
WHERE completed =1
GROUP BY played_level, user_id
ORDER BY time_take
LIMIT 20 

此查询显示占用最少时间的所有用户ID。

但是现在我想用最短的时间显示用户ID。

 user_id    played_level    time_take   
     1      18                19
     1      12                21
     2       3                25
     6       3                26
     2       2                27
     6       4                27
     1       8                32

预期产出:

user_id  played_level time_taken
 1         18          19
 2          3          25
 6          3          26  

7 个答案:

答案 0 :(得分:3)

首先从表

中选择所有distict user_id
                $distinct_users = "SELECT DISTINCT user_id FROM answer where addeddate BETWEEN :currdate1 AND :currdate2 AND completed=1";
                $distinct_users_data = $conn->prepare($distinct_users);
                $distinct_users_data->execute(array(':currdate1'=>$prev_date,':currdate2'=>$currdate2));
                $distinct_users_arr = $distinct_users_data->fetchAll();

现在找到此user_id的最短时间并将其存储在数组

                foreach($distinct_users_arr as $distict_data)
                    {
                    $user_ids=$distict_data['user_id'];


                $all_user_time = "SELECT user_id, played_level, sum( time_taken ) AS time_take FROM answer where addeddate BETWEEN :currdate1 AND :currdate2 
                                  AND completed=1 AND user_id=:user_id GROUP BY played_level, user_id ORDER BY time_take limit 1";
                $all_user_time_data = $conn->prepare($all_user_time);
                $all_user_time_data->execute(array(':currdate1'=>$prev_date,':currdate2'=>$currdate2,':user_id'=>$user_ids));
                $all_user_time_arr = $all_user_time_data->fetchAll();
                $all_count= $all_user_time_data->rowCount();
                foreach($all_user_time_arr as $leading_user)
                            {
                            $new_user_id= $leading_user['user_id'];
                            $new_time= $leading_user['time_take'];

                                $leader_board[] = array(
                                                'user_id'=>$new_user_id, 
                                                'time_taken'=>$new_time
                                            );

                            }


                    }

最后按时间排序该数组顺序。我们得到最终结果

foreach ($leader_board as $key => $row) 
                                         {
                                    $sorting[$key] = $row['time_taken'];
                                        }
                            array_multisort($sorting, SORT_ASC, $leader_board);

答案 1 :(得分:2)

虽然您可以使用join执行此操作,但这很复杂,因为您必须重复聚合。您也可以使用嵌套聚合执行此操作。困难的部分是获得最小值的played_level。以下查询使用技巧来使用substring_index() / group_concat()来获取该功能。这是没有limit子句的查询 - 我不太确定你想要限制什么:

select user_id,
       substring_index(group_concat(played_level order by time_take), ',', 1) as played_level,
       min(time_take) as time_take
from (SELECT user_id, played_level, sum( time_taken ) AS time_take
      FROM answer
      WHERE completed =1
      GROUP BY played_level, user_id
     ) a
group by user_id
ORDER BY time_take;

答案 2 :(得分:0)

SELECT DISTINCT

SELECT 
    DISTINCT user_id, 
    played_level, 
    sum( time_taken ) AS time_take
FROM answer
WHERE completed =1
GROUP BY played_level
ORDER BY time_take
LIMIT 20 

你也可以像这样使用GROUP BY

SELECT 
    user_id, 
    played_level, 
    sum( time_taken ) AS time_take
FROM answer
WHERE completed =1
GROUP BY user_id
ORDER BY time_take
LIMIT 20 

答案 3 :(得分:0)

我相信你的意思是:你想要每个用户完成的最后一级:

SELECT 
    user_id, 
    max(played_level) current user_level, 
    sum(time_taken) AS time_take
FROM answer
WHERE completed =1
GROUP BY user_id
ORDER BY time_take 
LIMIT 20 

答案 4 :(得分:0)

在这种情况下,你需要使用子查询

select
 user_id, 
    played_level, 
    min( time_taken ) AS time_take
from(
SELECT 
    user_id, 
    max(played_level) played_level, 
    sum( time_taken ) AS time_take
FROM answer
WHERE completed =1
GROUP BY user_id
ORDER BY time_take
LIMIT 20 
) a
group by user_id

答案 5 :(得分:0)

你可以尝试一下吗?

SELECT x.*
FROM (
    SELECT 
        user_id, 
        played_level, 
        SUM(time_taken) AS time_take
    FROM answer
    WHERE completed = 1
    GROUP BY played_level, user_id
) x INNER JOIN (
    SELECT played_level, user_id, MIN(time_take) AS mn
    FROM (
        SELECT 
            user_id, 
            played_level, 
            SUM(time_taken) AS time_take
        FROM answer
        WHERE completed = 1
        GROUP BY played_level, user_id
    ) y
    GROUP BY user_id, played_level
) z ON x.user_id = z.user_id
    AND x.played_level = z.played_level AND x.time_take = z.mn

内联视图z每个(user_id,playing_level)都有MIN(time_take),最后加入原始查询。

答案 6 :(得分:0)

您需要通过子查询使用JOIN:

SELECT user_id, played_level, time_taken
FROM answer
JOIN (
   SELECT user_id AS t_user_id, MIN(time_taken) AS min_time_taken
   FROM answer
   GROUP BY user_id
) t
ON answer.user_id = t.t_user_id AND answer.time_taken = t.min_time_taken
WHERE completed = 1
ORDER BY time_take
LIMIT 20