2

在 aMySQL 5.0的表中,我希望删除最旧的记录,直到某些数字字段的 SUM 达到某个称为 TOT(某个阈值)的值。

我在表中有以下字段:

ID, field0 (varchar), field1 (INT), field2 (INT), field3 (int), date

我需要一个查询来选择所有最旧的记录,直到达到总和值 (TOT)

SELECT ID, SUM(field1,field2,field3) as TOT 
    WHERE field0 = '$username' .... ORDER BY date ASC 

目的:删除较旧的记录,直到 3 个数字字段的 SUM 达到某个值 TOT。

有小费吗?谢谢

4

3 回答 3

0

因为你没有给你表的实际表描述。在我的回答中,我Worker在我的COMPANY数据库中使用 a :

在我的Worker表中,我有三个薪水字段,类似于 you field1field2& field3。实际描述如下:

mysql> DESC `Worker`;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| SSN     | varchar(64) | NO   |     | NULL    |       |
| name    | varchar(64) | YES  |     | NULL    |       |
| salary1 | int(11)     | YES  |     | NULL    |       |
| salary2 | int(11)     | YES  |     | NULL    |       |
| salary3 | int(11)     | YES  |     | NULL    |       |
| Date    | int(11)     | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
6 rows in set (0.00 sec)

在此表中,我添加Date为整数(您可以在 MySQL 中使用实际数据类型)。

假设表有以下元组:

mysql> SELECT * FROM `Worker` ORDER BY `Date` ASC ;
+-----+---------+---------+---------+---------+------+
| SSN | name    | salary1 | salary2 | salary3 | Date |
+-----+---------+---------+---------+---------+------+
| 3   | Sumit   |     250 |     150 |     100 |    2 |
| 4   | Harsh   |     500 |    -150 |     900 |    2 |
| 5   | ONE     |     100 |     170 |     100 |    9 |
| 2   | Rahul   |     300 |      15 |      30 |   10 |
| 1   | Grijesh |     200 |     100 |      50 |   13 |
| 7   | THREE   |    1000 |      17 |    -200 |   21 |
| 6   | TWO     |      50 |    -170 |     200 |   27 |
+-----+---------+---------+---------+---------+------+  

ASC 订单显示在上面的查询中,日期是我说的类型

假设我需要删除所有的旧工人,他们的工资总和刚刚超过NN在你的情况下就像阈值 TOT)。要选择年长的工人,我需要按同意 ( ASC ) 顺序 对Worker表格进行排序。

您可以假设的日期作为工人加入公司的日期。这么老是根据加入的日期那是经验

在编写选择查询之前,我向您展示了一些结果:

mysql> SELECT * , `salary1` + `salary2` + `salary3` AS TSalary  
    -> FROM `Worker` ORDER BY DATE ASC ; 

+-----+---------+---------+---------+---------+------+---------+
| SSN | name    | salary1 | salary2 | salary3 | Date | TSalary |
+-----+---------+---------+---------+---------+------+---------+
| 3   | Sumit   |     250 |     150 |     100 |    2 |     500 |
| 4   | Harsh   |     500 |    -150 |     900 |    2 |    1250 |
| 5   | ONE     |     100 |     170 |     100 |    9 |     370 |
| 2   | Rahul   |     300 |      15 |      30 |   10 |     345 |
| 1   | Grijesh |     200 |     100 |      50 |   13 |     350 |
| 7   | THREE   |    1000 |      17 |    -200 |   21 |     817 |
| 6   | TWO     |      50 |    -170 |     200 |   27 |      80 |
+-----+---------+---------+---------+---------+------+---------+
7 rows in set (0.01 sec)  

TSalary是工人获得的总工资,它是三个组成部分的总和salary1salary2& salary3如上面的查询所示

每个级别的工资总和是多少(对于表的每个子集):

+-----+---------+---------+---------+---------+------+---------+
| SSN | name    | salary1 | salary2 | salary3 | Date | TSalary | SUM(TSalary) at
+-----+---------+---------+---------+---------+------+---------+ each level
| 3   | Sumit   |     250 |     150 |     100 |    2 |     500 |500
| 4   | Harsh   |     500 |    -150 |     900 |    2 |    1250 |500 + 1250= 1750
| 5   | ONE     |     100 |     170 |     100 |    9 |     370 |1750 + 370= 2120
| 2   | Rahul   |     300 |      15 |      30 |   10 |     345 |2120 + 345= 2465
| 1   | Grijesh |     200 |     100 |      50 |   13 |     350 |2465 + 350= 2815 
| 7   | THREE   |    1000 |      17 |    -200 |   21 |     817 |2815 + 817= 3632
| 6   | TWO     |      50 |    -170 |     200 |   27 |      80 |3632 + 80 = 3712
+-----+---------+---------+---------+---------+------+---------+     

我写了一个查询来选择有工资总和的老工人<= N

N = 1500下面是示例:(正如我上面计算的那样,我猜应该选择两行

SELECT `ssn`, `name`, `salary1` , `salary2` , `salary3` 
FROM ( SELECT `ssn`, 
              `name`, 
              `salary1` , 
              `salary2` , 
              `salary3`, 
              (@total:=@total+ `salary1` + `salary2` + `salary3`) as TSalary  
       FROM `Worker`, (select @total:=0) t 
       ORDER BY `Date` ASC ) AS `some_worker`  
WHERE (TSalary -(`salary1` + `salary2` + `salary3`))  <= 1500;

+-----+-------+---------+---------+---------+
| ssn | name  | salary1 | salary2 | salary3 |
+-----+-------+---------+---------+---------+
| 3   | Sumit |     250 |     150 |     100 |
| 4   | Harsh |     500 |    -150 |     900 |
+-----+-------+---------+---------+---------+
2 rows in set (0.00 sec)

注意:只选择了两个,因为包括第三个意味着超过 N (= 1500)。

现在假设N = 2000:(并且正如我上面计算的那样,我猜应该选择两行

SELECT `ssn`, `name`, `salary1` , `salary2` , `salary3` 
FROM ( SELECT `ssn`, 
              `name`, 
              `salary1` , 
              `salary2` , 
              `salary3`, 
              (@total:=@total+ `salary1` + `salary2` + `salary3`) as TSalary  
       FROM `Worker`, (select @total:=0) t 
       ORDER BY `Date` ASC ) AS `some_worker`  
WHERE (TSalary -(`salary1` + `salary2` + `salary3`))  <= 2000;

+-----+-------+---------+---------+---------+
| ssn | name  | salary1 | salary2 | salary3 |
+-----+-------+---------+---------+---------+
| 3   | Sumit |     250 |     150 |     100 |
| 4   | Harsh |     500 |    -150 |     900 |
+-----+-------+---------+---------+---------+
| 5   | ONE   |     100 |     170 |     100 |
+-----+-------+---------+---------+---------+
3 rows in set (0.00 sec)

此查询在此示例中运行良好,但可能适用于长表,但这是完成工作的一种方式。

试试看!!

此外,您可以根据需要更改外部条件中的相等条件(我对您的阈值定义有点困惑。如果您举个例子可能会很好)

于 2013-01-27T04:30:36.720 回答
0

这是一个实现存储过程的地方

  1. 你可以得到总记录集,
  2. 按 id 或 insert-date 排序,并且
  3. 不断对字段求和,直到达到目标总数,然后
  4. 在您的订购列表中选择最新的,并且
  5. 删除该范围之外的所有内容。
于 2013-01-23T15:26:15.533 回答
0

您可以通过这种方式计算累积总和:

SELECT ID,
       (select SUM(field1 + field2 + field3) from t t2 where t2.date <= t.date and t2.field0 = tempdb.field0) as cumsum
from t
WHERE field0 = '$username' 

我认为以下工作在 MySQL 中进行删除:

delete from t
where t.id in (select id
               from (SELECT ID,
                            (select SUM(field1 + field2 + field3) from t t2 where t2.date <= t.date and t2.field0 = tempdb.field0) as cumsum
                     from t
                     WHERE field0 = '$username' 
                    ) tsum
                where cumsum <= YOURTHRESHOLD
              )

deleteMySQL 对语句中的自连接很挑剔。我认为双子查询解决了这个问题。

注意:此代码未经测试,因此可能包含语法错误。

于 2013-01-23T18:56:34.110 回答