mysql查询排序和排序

时间:2013-06-06 09:48:30

标签: mysql optimization

假设我有一个名为“users”的表,它有40行记录,每行都有字段:

id, firstname, group_id, login_count, stay_on_page_count

小组已经

administrator (1), manager (2), employee (3)

是否可以创建一个以这种方式对行进行排序和排序的查询

    group _id      stay_on_page_count  login_count
    =========      ==================  ===========
    1              100mins             100
    1              90mins              90
    2              100mins             100
    3              100mins             100

    1              80mins              80
    1              70mins              70
    2              90mins              90
    3              90mins              90

    1              60mins              60
    1              50mins              50
    2              80mins              80
    3              80mins              80

    1              40mins              40
    1              30mins              30
    2              70mins              70
    3              70mins              70

基本上我想使用查询结果创建一个4x4网格视图。伪代码可能是

SELECT all FROM user table and to group the result in to cluster of 4, 
    while each 4 should have ORDER BY group_id ASC as first priority (1,1,2,3) 
    AND stay_on_page_count ORDER BY DESC as second priority, 
    AND login_count ORDER BY DESC as last or third priority

我不知道伪代码是否解释得足够,但这是我能想出的唯一内容:)

如果它可能,那么它会牺牲性能吗? 有没有更好的方法来实现这个目标?

我正在使用Mysql和PHP(CakePHP 2.x)

谢谢

2 个答案:

答案 0 :(得分:2)

一种方法(使用summarised作为保存问题中列出的汇总值的表格):

select * from
(select s1.*, 
        @rank1:=@rank1+1 as rankcalc,
        floor(@rank1/2) rankgroup,
        @rank1%2 rankingroup
 from (select @rank1:=1) r1
 cross join
 (select * from summarised where group_id=1 order by stay_on_page_count desc) s1
 union all
 select s2.*, 
        @rank2:=@rank2+1 as rankcalc,
        @rank2 rankgroup,
        2 rankingroup
 from (select @rank2:=0) r2
 cross join
 (select * from summarised where group_id=2 order by stay_on_page_count desc) s2
 union all
 select s3.*, 
        @rank3:=@rank3+1 as rankcalc,
        @rank3 rankgroup,
        3 rankingroup
 from (select @rank3:=0) r3
 cross join
 (select * from summarised where group_id=3 order by stay_on_page_count desc) s3
) sq order by rankgroup, rankingroup

SQLFiddle here

请注意,此解决方案依赖于按子查询中指定的顺序进行计算的排序,而不是由优化程序覆盖 - 这应该适用于当前版本的MySQL,但可能无法在MariaDB中工作(开源MySQL的分支)或MySQL的未来版本。

答案 1 :(得分:0)

虽然这会产生你想要的顺序,但它却是一种强制和硬编码的努力。它使得一些假设如login_count始终在您列出的范围内。

SELECT group_ID, Stay_on_Page_count, Login_Count, myset 
FROM (
SELECT group_ID, Stay_on_Page_Count, Login_Count, 1 as mySet
FROM USERS
WHERE (GROUP_ID=1 and Login_count >= 90) OR (group_ID in (2,3) and Login_Count=100)
UNION
SELECT group_ID, Stay_on_Page_Count, Login_Count, 2 as mySet
FROM USERS
WHERE (GROUP_ID=1 and Login_count Between 70 and 80) 
  OR (group_ID in (2,3) and Login_Count=90)
UNION
SELECT group_ID, Stay_on_Page_Count, Login_Count, 3 as mySet
FROM USERS
WHERE (GROUP_ID=1 and Login_count Between 50 and 60) 
  OR (group_ID in (2,3) and Login_Count=80)
UNION
SELECT group_ID, Stay_on_Page_Count, Login_Count, 4 as mySet
FROM USERS
WHERE (GROUP_ID=1 and Login_count Between 30 and 40) 
  OR (group_ID in (2,3) and Login_Count=70))
ORDER BY myset, group_ID, Login_count Desc