7

我的桌子

+------+-------+--------+
| NAME | MARKS | POINTS |
+------+-------+--------+
| S1   |    53 | (null) |
| S2   |    55 | (null) |
| S3   |    56 | (null) |
| S4   |    55 | (null) |
| S5   |    52 | (null) |
| S6   |    51 | (null) |
| S7   |    53 | (null) |
+------+-------+--------+

参考:http ://www.sqlfiddle.com/#!2/5d046/1

我想在最高分上加 3、2、1 分。这里 S3 得 3 分,S2、S4 得 2 分,S1、S7 得 1 分。

最终输出看起来,

+------+-------+--------+
| NAME | MARKS | POINTS |
+------+-------+--------+
| S1   |    53 |   1    |
| S2   |    55 |   2    |
| S3   |    56 |   3    |
| S4   |    55 |   2    |
| S5   |    52 |   0    |
| S6   |    51 |   0    |
| S7   |    53 |   1    |
+------+-------+--------+

请帮忙

4

4 回答 4

4

My suggestion is that you first calculate the ranking of each mark, and then use that in a case statement in an update.

The following query shows one way to calculate the ranking:

select t.*,
       @rn := if(@marks = marks, @rn, @rn + 1) as ranking,
       @marks := marks
from myTable t cross join
     (select @rn := 0, @marks := -1) const
order by t.marks desc;

(As a note: I am a bit uncomfortable with this method, because MySQL does not guarantee the order of evaluation of the two expressions with constants. If @marks were set before @rn, then it wouldn't work. In practice, that does not seem to happen. And, this is more efficient that the equivalent with a correlated subquery.)

You can then put this into an update using join:

update myTable join
       (select t.*,
               @rn := if(@marks = marks, @rn, @rn + 1) as ranking,
               @marks := marks
        from myTable t cross join
             (select @rn := 0, @marks := -1) const
        order by t.marks desc
       ) mr
       on myTable.Name = mr.Name
    set myTable.Points := (case when mr.ranking = 1 then 3
                                when mr.ranking = 2 then 2
                                when mr.ranking = 3 then 1
                                else 0
                           end);

This has been tested on your SQL Fiddle.

于 2013-09-09T11:06:56.610 回答
1

您可以通过变量(参见其他答案中的示例)或通过case

select 
  myTable.*,
  case
    when max1.marks is not null then 3
    when max2.marks is not null then 2
    when max3.marks is not null then 1
    else 0
  end as score
from
  myTable
  LEFT JOIN
  (select marks from myTable order by marks desc limit 1) AS max1
  ON myTable.marks=max1.marks
  LEFT JOIN
  (select marks from myTable order by marks desc limit 2,1) AS max2
  ON myTable.marks=max2.marks
  LEFT JOIN
  (select marks from myTable order by marks desc limit 3,1) AS max3
  ON myTable.marks=max3.marks;

演示可以在这里找到。

于 2013-09-09T11:17:03.053 回答
1
UPDATE myTable t1
INNER JOIN 
(
SELECT @row:=@row-1 AS RowPoints, Marks
FROM (
  SELECT Marks
  FROM myTable
  GROUP BY Marks
  ORDER BY Marks DESC
  LIMIT 3
) AS TopMarks
INNER JOIN (SELECT @row:=4) AS RowInit
) AS AddPoints ON t1.Marks = AddPoints.Marks
SET Points = COALESCE(Points, 0) + AddPoints.RowPoints;

这应该工作得很好。您应该在 Marks 列上建立索引。

于 2013-09-09T11:11:20.187 回答
1

最简单的方法是:

SELECT t.Name Name, t.Marks Marks,

 (CASE WHEN Marks = (Select max(marks) from mytable) THEN 3 ELSE 0 END+

CASE WHEN Marks = (Select min(marks) from (Select distinct marks 
    from mytable order by marks desc limit 2) a) THEN 2 ELSE 0 END+

CASE WHEN Marks = (Select min(marks) from (Select distinct marks 
    from mytable order by marks desc limit 3) b) THEN 1 ELSE 0 END)

AS `Points`
FROM mytable t;

SQL小提琴

于 2013-09-09T12:09:27.820 回答