按日期更新行顺序

时间:2016-07-18 06:45:25

标签: mysql

我早上已经问了这个问题,但没有得到任何答案。所以我删除了之前的一个,并再次问这个因为我被困了很长一段时间。希望你们能帮助我。

我有一个名为overtime的表格如下:

| total | remain |              t_date |
|-------|--------|---------------------|
|     3 |      0 | 2016-01-01 12:20:00 |
|     4 |      0 | 2016-02-01 13:10:00 |
|     2 |      0 | 2016-03-01 14:40:00 |
|     3 |      0 | 2016-04-01 10:20:00 |
|     5 |      2 | 2016-05-01 17:20:00 |

我想更新列保留order by t_date desc,我也有一个输入参数,假设它是$ h = 9,预期结果是:

| total | remain |              t_date |
|-------|--------|---------------------|
|     5 |      5 | 2016-05-01 17:20:00 | -- remain will be updated to 5 cause total = 5, then $h(6) = $h(9) - (total(5) - remain(2)) 
|     3 |      3 | 2016-04-01 10:20:00 | -- remain will be updated to 3 cause total = 3, then $h(3) = $h(6) - (total(3) - remain(0)) 
|     2 |      2 | 2016-03-01 14:40:00 | -- remain will be updated to 2 cause total = 2, then $h(1) = $h(3) - (total(2) - remain(0))
|     4 |      1 | 2016-02-01 13:10:00 | -- remain will be updated to 1 cause $h only has 1, then $h will be 0
|     3 |      0 | 2016-01-01 12:20:00 | -- cause $h = 0, this row has no need to be updated

编辑: 示例数据如上所述,我想要做的是更新列remainremain'值基于总和输入参数(假设它是9):

  • 更新订单为order by t_date desc。例如,我必须首先更新2016-05-01 17:20:00行,然后更新2016-04-01 10:20:00,然后更新2016-03-01 14:40:00等等......
  • 参数为9,它将分配给每一行,remain应更新为total的值。例如,第一行2016-05-01 17:20:00total = 5且remain = 2,因此remain将更新为5,参数将减去total - remain,它将是6并执行下一行的分配,直到行2016-02-01 13:10:00,参数为1,因此此行remain只需要更新1.另一行不需要更新。

Here is SQLFiddle demo
如果有任何不明确的问题,请发表评论,我可以解释一下。

感谢任何帮助。提前谢谢。

3 个答案:

答案 0 :(得分:1)

您可以使用使用变量 @h 进行计算的子查询:

update   overtime 
join     (select   t_date,
                   least(@h,total) 
                      + if(least(@h,total) + remain <= total, remain, 0)  new_remain,
                   @h := greatest(0, @h - (total - remain)) h
          from     overtime,
                   (select @h := 9) init
          order by t_date desc
         ) as calc
      on overtime.t_date = calc.t_date   
set      overtime.remain := calc.new_remain;

请参阅此SQL fiddle

答案 1 :(得分:1)

SELECT QUERY:

    SELECT 
    *,
    IF(
        (IF(@h <= 0,0,IF(@h >= total,total, @h)) + remain) <= total, 
        (IF(@h <= 0,0,IF(@h >= total,total, @h)) + remain), 
        (IF(@h <= 0,0,IF(@h >=  total,total, @h)))
      ) allocated,
    @h := @h - (total - remain)
    FROM overtime
    CROSS JOIN (SELECT @h := 9) var
    ORDER BY t_date DESC

Demo of SELECT

更新查询:

UPDATE 
overtime OT 
INNER JOIN 

(
        SELECT 
        *,
        IF(
          (IF(@h <= 0,0,IF(@h >= total,total, @h)) + remain) <= total, 
          (IF(@h <= 0,0,IF(@h >= total,total, @h)) + remain), 
          (IF(@h <= 0,0,IF(@h >=  total,total, @h)))
         ) allocated,
    @h := @h - (total - remain)
    FROM overtime
    CROSS JOIN (SELECT @h := 9) var
    ORDER BY t_date DESC
) AS t
ON OT.t_date = t.t_date
SET OT.remain = t.allocated;

WORKING DEMO

Demo显示按上述update查询更新后按日期降序排序的表格数据。

更多

See Demo for h=2

答案 2 :(得分:1)

您必须使用子查询执行此操作,如下所示:

update overtime t1
join (
  select overtime.*,
  total - remain, IF(@h > (total - remain), total, @h + remain) as h,
  @h := IF(@h > (total - remain), @h - (total - remain), 0)
  from overtime
  cross join (
      select @h := 9
  ) t
  order by t_date desc
) t2 on t1.t_date = t2.t_date
set t1.remain = t2.h;

Demo Here