时间:2016-05-01 02:16:21

标签: mysql sql

假设我有以下MySQL表(假设表名为't'

|-----|------------------------------|--------|------------|
|  ID | Movie                        | Rating | Purchased  |
|-----|------------------------------|--------|------------|
|  1  | Big Adventure                | G      | 2002-03-06 |
|  2  | Shiny Things, The            | PG     | 2002-03-06 |
|  3  | End of the Line              | R      | 2001-02-05 |
|  4  | A Rat named Darcy            | G      | 2003-04-19 |
|  5  | Head First Rules             | R      | 2003-04-19 |
|  6  | Mad Clowns                   | R      | 1999-11-20 |
|  7  | Greg: The Untold Story       | PG     | 2001-02-05 |
|  8  | Potentially Habitable Planet | PG     | 2001-02-05 |
|  9  | Weird Things from Space      | PG     | 2003-04-19 |
| 10  | Shark Bait                   | G      | 1999-11-20 |
| 11  | Take it Back                 | R      | 2001-02-05 |
| 12  | The White Mare               | PG     | 2006-08-15 |
| 13  | Simuduck Exposed             | PG     | 2001-05-06 |
|-----|------------------------------|--------|------------|

我想要做的是从表中获取项目并满足以下条件:

  1. 按升序排列,按降序排列日期
  2. 显示每个评级中的第一个,然后是每个评级的第二个项目,依此类推。
  3. 如果其中一个评分已用尽',则转到其他两个评级,依此类推,直至显示所有项目
  4. 如果这对您来说很困惑,请不要担心,确实如此。为了更好地解释,以下是我从上表中得到的结果:

    |-----|------------------------------|--------|------------|
    |  ID | Movie                        | Rating | Purchased  |
    |-----|------------------------------|--------|------------|
    |  4  | A Rat named Darcy            | G      | 2003-04-19 |
    | 12  | The White Mare               | PG     | 2006-08-15 |
    |  5  | Head First Rules             | R      | 2003-04-19 |
    |  1  | Big Adventure                | G      | 2002-03-06 |
    |  9  | Weird Things from Space      | PG     | 2003-04-19 |
    | 11  | Take it Back                 | R      | 2001-02-05 |
    | 10  | Shark Bait                   | G      | 1999-11-20 |
    |  2  | Shiny Things, The            | PG     | 2002-03-06 |
    |  3  | End of the Line              | R      | 2001-02-05 |
    | 13  | Simuduck Exposed             | PG     | 2001-05-06 |
    |  6  | Mad Clowns                   | R      | 1999-11-20 |
    |  7  | Greg: The Untold Story       | PG     | 2001-02-05 |
    |  8  | Potentially Habitable Planet | PG     | 2001-02-05 |
    |-----|------------------------------|--------|------------|
    

    如果您检查上面的结果表,您会注意到以下内容:

    1. 选择的第一张电影是"一只名叫达西的老鼠"。选择此电影是因为

      a)它是G评级电影的第一(评级按升序排列)

      b)并且G评级电影中的最高日期(日期按降序排列)

    2. 选择的第二张电影是" The White Mare"。选择此电影是因为

      a)它是PG评级电影的第一(评级按升序排列)

      b)并且PG评分电影中的最高日期(日期按降序排列)

    3. 选择的第三张电影是" Head First Rules"。选择此电影是因为

      a)它是R评级电影的第一(评级按升序排列)

      b)并且R评级电影中的最高日期(日期按降序排列)

    4. 选择的第四部电影是" Big Adventure"。选择此电影是因为

      a)它是G评级电影的第二(评级按升序排列)

      b)并且G评级电影中的第二高日期(日期按降序排列)

    5. 选择的第五张电影是#34;来自Space"的奇怪事物。选择此电影是因为

      a)它是PG评级电影的第二(评级按升序排列)

      b)并且PG评级影片中的第二高日期(日期按降序排列)

    6. 等等。我希望你现在能想出这个模式。

      所以,我的问题是,有没有办法在一个sql语句中这样做?如果没有,或者解决方案是性能密集型的,那么您对包含mysql和编程语言解决方案(php)的解决方案有何建议?

      非常感谢。

2 个答案:

答案 0 :(得分:1)

您可以通过枚举每个评级的值,然后在外部查询中执行order by来执行此操作:

select ID, Movie, Rating, Purchased 
from (select t.*,
             (@rn := if(@r = rating, @rn + 1,
                        if(@r := rating, 1, 1)
                       )
             ) as rn
      from t cross join
           (select @r := '', @rn := 0) params
      order by rating, Purchased desc
     ) r
order by rn, rating;

答案 1 :(得分:1)

我会使用MySQL用户定义的变量。

请注意,MySQL参考手册警告以这种方式使用的用户定义变量的行为是 undefined 。 (此声明取决于MySQL执行的特定操作顺序,但不保证。)

 SELECT r.id
      , r.movie
      , r.rating
      , r.purchased 
   FROM ( -- 
          SELECT @rownum := IF(t.rating = @rating, @rownum + 1, 1) AS seq
               , t.id
               , t.movie
               , @rating := t.rating AS rating
               , t.purchased
            FROM ( SELECT @rating := NULL, @rownum := 0) i
           CROSS
            JOIN t t 
           ORDER BY t.rating ASC, t.purchased DESC
        ) r
  ORDER BY r.seq ASC, r.rating ASC

内联视图我初始化用户定义的变量,因此语句执行不会受当前变量中的值的影响。

内联视图r对指定序列中的行进行排序,然后将当前行与上一行的值进行比较,以确定@rownum是否应增加1(当评级与前一个相同时),或者在遇到新的评级时重置为1.

当前行的rating列的值被“保存”到用户定义的变量@rating中,因此可以将其与下一行的rating列的值进行比较(处理下一行时)。 )

对于每一行,分配给@rownum的值将在名为seq。

的列中返回

外部查询首先根据seq列(已分配的rownum值)重新排序集合,然后是评级。