假设我有一个返回以下结果的查询:
| val | type | i |
----------------------
| 59 | 1 | 1 |
| 40 | 2 | 2 |
| 12 | 1 | 3 |
| 3 | 2 | 4 |
| 24 | 1 | 5 |
| 30 | 1 | 6 |
| 98 | 2 | 7 |
| 45 | 2 | 8 |
| 46 | 1 | 9 |
val = an arbitrary number
type = 1 or 2
i = auto increment column, just for reference
我想执行以下减法:
A - B
A: Value of row of type '2'
B: Value of row above A of type '1' if it exists, but without crossing a row of type '2'
我真的希望有道理..
一些例子:
Row i=2 is of type 2. So the first row above it of type 1 is i=1.
So the subtraction will be: 40 - 59 = -19
Row i=7 is of type 2. So the first row above it of type 1 is i=6
So the subtraction will be: 98 - 30 = 68
Row i=8 is of type 2. But if we go above we cross a value of type 2.
So the subtraction should return 0, or be ignored, whichever is simplest.
最后,结果应该返回一列值,其中type = 1和减去的值。
例如:
| val | diff |
--------------
| 59 | -19 |
| 12 | -9 |
| 24 | 0 | ***
| 30 | 68 |
| 46 | 0 | ***
*** Return diff=0 if the subtraction was never made for this row.
我有查询获取我的初始表。我知道如何进行减法(在实际情况下,val是一个日期,但我在这个例子中保持简单)。
我唯一不知道该怎么做的是基于MySQL中的不同行执行逻辑。例如,如何根据某些条件找到最近的行,然后引用该行以对其执行某些操作?是否有一种方法可以引用当前的'i'并在(i处的行)减去(i-1处的行)或类似的东西上进行一次subrtaction。
我已经花了很多时间在这上面,而我正准备放弃并在PHP中完成并取得性能。作为最后的手段,我问这里是否有办法直接在mysql中完成所有这些工作?
我不需要完整的解决方案,因为这是非常复杂的要求,但我会接受您可以给我的任何建议或指示。我不是MySQL最好的,所以也许我错过了一些简单的东西。
感谢。
答案 0 :(得分:2)
SELECT t1.val AS val, IFNULL( t2.val, t1.val ) - t1.val AS diff FROM my_table AS t1
LEFT JOIN my_table AS t2 ON( t2.type = 2 AND t2.i = t1.i + 1 )
WHERE t1.type = 1 ORDER BY t1.i;
根据您的数据进行测试,结果:
| val | diff |
--------------
| 59 | -19 |
| 12 | -9 |
| 24 | 0 |
| 30 | 68 |
| 46 | 0 |
答案 1 :(得分:0)
您需要的是一张桌面上带有cursor的存储过程。这应该是一个很好的起点。
CREATE PROCEDURE curdemo()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE val, type, prev_val, prev_type INT;
DECLARE cur1 CURSOR FOR SELECT val, type, i from your_table;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO val, tpye, i;
IF done THEN
LEAVE read_loop;
END IF;
-- your logic goes here, sorry, not sure I understood correctly, but roughly here it goes
IF type = 2 THEN
IF prev_type is not null and prev_type = 1 THEN
INSERT INTO result_table VALUES (prev_val, val - prev_val);
END IF;
END IF;
SET prev_val = val;
SET prev_type = type;
END LOOP;
CLOSE cur1;
END;
答案 2 :(得分:0)
也许你可以这样做:
select t1.val, (t1.val - t2.val) as diff
from table as t1, table as t2
where t1.i = t2.i + 1
and t1.type = 1
and t2.type = 2
用零选择你可以这样做:
select t1.val, (t1.val - t2.val)*(t2.type - t1.type) as diff
from table as t1, table as t2
where t1.i = t2.i + 1
and t1.type = 1
在有一个时获得最后一个零,加入:
select val, 0 as diff from
select val
from table
order by i desc
limit 1