从distinct <column> </column>中选择多行

时间:2012-03-27 11:07:43

标签: mysql

我有一个'events'的mysql表,其中包含'category'和'visited'的列。一个事件有3个类别。 'visited'计算活动页面访问次数。我希望从3个类别中的每一个中获得前两个访问过的事件。

这是一个示例表

访问的id类别 32个1 23
33个2 12
34个3 42
35个1 53
36个2 24
37个3 84
38个1 12
39个2 75
40个3 22

我需要按此顺序显示这些行(id =):35,32,39,36,37,34。我所拥有的代码每个类别只返回1行,我相信严格限制为返回1行(我没写过。):

$categories=mysql_query("select distinct category from events");
while($row_cat=mysql_fetch_array($categories)){
    $row=mysql_fetch_array(mysql_query("select * from events where category='".$row_cat['category']."' order by visited desc"));
    echo $row['id'].", ";
}

该代码显示:35,39,37,

我觉得答案可能非常简单,但它仍然在逃避我。提前谢谢你的帮助。

3 个答案:

答案 0 :(得分:1)

怎么样?
SELECT category, GROUP_CONCAT(id ORDER BY visited DESC)
    FROM events
    GROUP BY category

对于您的原始代码:这是因为您只需要一行。

你的while循环迭代所有类别。对于他们每个人。它发出一个查询并要求一行。您需要2个嵌套循环来查询所有内容。所以“纯粹的MySQL”解决方案要好得多。


但是如果你需要比你原来说的更多,你可能更好地通过嵌套循环PHP-side一个一个地执行这些查询:

$categories=mysql_query("select distinct category from events");
while($row_cat=mysql_fetch_array($categories)){
    $inner_res=mysql_query("select * from events where category='".mysql_real_escape_string($row_cat['category'])."' order by visited desc"); 
    while($inner_row=mysql_fetch_array($inner_res)){
        echo $inner_row['id'].", ";
    }
}

答案 1 :(得分:1)

@glglgl方法非常酷+1,你也可以使用find in set函数来优化它并逐行获得每个类别的前3个事件:

select e0.*
from 
   events e0
inner join
   (SELECT category, 
       GROUP_CONCAT(id ORDER BY visited DESC) as events
   FROM events
   GROUP BY category) C
     on
        e0.category = c.category and
        find_in_set( e0.event, c.events ) < 3

小心,如果你有很多事件,这可能会很慢。

免责声明:未经测试。

答案 2 :(得分:0)

SELECT e.*
FROM 
        ( SELECT DISTINCT category
          FROM events 
        ) AS ed
    JOIN
        events AS e
            ON  e.category = ed.category
            AND e.visited >=
                ( SELECT visited 
                  FROM events AS ei
                  WHERE ei.category = ed.category
                  ORDER BY visited DESC
                  LIMIT 1 OFFSET 1
                )