Điều này được thực hiện tốt hơn ở cấp ứng dụng, nhưng nói cho vui, đây là ở cấp cơ sở dữ liệu:
select `user`, `start`, `stop`, diff from (
select
t.*
, if(@prev_user = `user`, (`stop` - @prev) * -1, 0) as diff
, @prev := `start`
, @prev_user := `user`
from
t
, (select @prev := null, @prev_user := null) var_init
order by `user`, `start` desc
) sq
order by `user`, `start`
- xem nó hoạt động trực tiếp trong sqlfiddle
Lưu ý rằng không có hàm lag / dẫn trong MySQL. Tất cả những gì bạn có thể làm là sử dụng các biến. SELECT
mệnh đề được xử lý từng dòng một. Vì vậy, bạn có thể gán giá trị của hàng hiện tại trong các dòng cuối cùng của SELECT
và do đó sử dụng biến này làm giá trị của "hàng trước" trong các dòng đầu tiên của SELECT
.
Cũng lưu ý rằng ORDER BY
là rất quan trọng. Một bảng không được sắp xếp. Dữ liệu trong DBMS quan hệ không được sắp xếp trừ khi bạn chỉ định một thứ tự với ORDER BY
mệnh đề.
- đọc thêm về cách sử dụng các biến trong truy vấn tại đây
CHỈNH SỬA:
Thay đổi nó thành
UPDATE inactivitytmp
JOIN (
SELECT
inactivitytmp.*
, if(@prev_user_id = `user_id`, (`end_ts` - @prev) * -1, 0) as diff2
, @prev := `start_ts`
, @prev_user_id := `user_id`
FROM
inactivitytmp
, (SELECT @prev := null, @prev_user_id := null) var_init
ORDER BY `user_id`, `start_ts` DESC
) query_alias
ON inactivitytmp.user_id=query_alias.user_id AND inactivitytmp.start_ts=q uery_alias.start_ts AND inactivitytmp.end_ts=query_alias.end_ts
SET inactivitytmp.diff=query_alias.diff2;