SQL - 在 MySQL 中循环遍历 table 的每一行?
SQL - Looping through ever row of table in MySQL?
所以我有 2 个 table、communication
和 movement
。
communication
的列 fromID
、timestamp
包含呼叫者 ID 和呼叫时间。然后我有另一个 table movement
有 ID
,timestamp
,x
,y
, 有一个人的 ID, 他们的位置(x,y)
,以及他们在该位置的时间。
我想编写一个如下所示的查询:
For every single row of communication(R)
SELECT * FROM movement m
WHERE m.ID = R.fromID && m.timestamp <= R.timestamp
ORDER BY timestamp
基本上,这是在为给定的 communication timestamp
找到最接近的 movement timestamp
。在那之后,最终,我想根据 movement
数据找到呼叫的位置 (x,y)
。
我该怎么做?我知道有一种基于集合的方法,但我不想那样做。我调查了 cursors
,但我觉得这方面的表现很糟糕。
那么有没有办法用循环来做到这一点?我基本上想遍历 communication
的每一行并获得结果。
我试过这样的事情:
DELMITER $$
CREATE PROCEDURE findClosestTimestamp()
BEGIN
DECLARE commRowCount DEFAULT 0;
DECLARE i DEFAULT 0;
DECLARE ctimestamp DEFAULT 0;
SELECT COUNT(*) FROM communication INTO commRowCount;
SET i = 0;
WHILE i < commRowCount DO
SELECT timestamp INTO ctimestamp FROM communication c
SELECT * FROM movement m
WHERE m.vID = c.fromID && m.timestamp <= R.timestamp
END$$
DELIMITER ;
但我知道那是完全错误的。
唯一的方法是游标吗?我在互联网上的任何地方都找不到这样的例子,而且我对 SQL.
中的程序完全陌生
任何指导将不胜感激,谢谢!!
让我们看看我是否可以使用光标为您指明正确的方向:
delimiter $$
create procedure findClosestTimeStamp()
begin
-- Variables to hold values from the communications table
declare cFromId int;
declare cTimeStamp datetime;
-- Variables related to cursor:
-- 1. 'done' will be used to check if all the rows in the cursor
-- have been read
-- 2. 'curComm' will be the cursor: it will fetch each row
-- 3. The 'continue' handler will update the 'done' variable
declare done int default false;
declare curComm cursor for
select fromId, timestamp from communication; -- This is the query used by the cursor.
declare continue handler for not found -- This handler will be executed if no row is found in the cursor (for example, if all rows have been read).
set done = true;
-- Open the cursor: This will put the cursor on the first row of its
-- rowset.
open curComm;
-- Begin the loop (that 'loop_comm' is a label for the loop)
loop_comm: loop
-- When you fetch a row from the cursor, the data from the current
-- row is read into the variables, and the cursor advances to the
-- next row. If there's no next row, the 'continue handler for not found'
-- will set the 'done' variable to 'TRUE'
fetch curComm into cFromId, cTimeStamp;
-- Exit the loop if you're done
if done then
leave loop_comm;
end if;
-- Execute your desired query.
-- As an example, I'm putting a SELECT statement, but it may be
-- anything.
select *
from movement as m
where m.vID = cFromId and m.timeStamp <= cTimeStamp
order by timestampdiff(SECOND, cTimeStamp, m.timeStamp)
limit 1;
end loop;
-- Don't forget to close the cursor when you finish
close curComm;
end $$
delimiter ;
参考文献:
所以我有 2 个 table、communication
和 movement
。
communication
的列 fromID
、timestamp
包含呼叫者 ID 和呼叫时间。然后我有另一个 table movement
有 ID
,timestamp
,x
,y
, 有一个人的 ID, 他们的位置(x,y)
,以及他们在该位置的时间。
我想编写一个如下所示的查询:
For every single row of communication(R)
SELECT * FROM movement m
WHERE m.ID = R.fromID && m.timestamp <= R.timestamp
ORDER BY timestamp
基本上,这是在为给定的 communication timestamp
找到最接近的 movement timestamp
。在那之后,最终,我想根据 movement
数据找到呼叫的位置 (x,y)
。
我该怎么做?我知道有一种基于集合的方法,但我不想那样做。我调查了 cursors
,但我觉得这方面的表现很糟糕。
那么有没有办法用循环来做到这一点?我基本上想遍历 communication
的每一行并获得结果。
我试过这样的事情:
DELMITER $$
CREATE PROCEDURE findClosestTimestamp()
BEGIN
DECLARE commRowCount DEFAULT 0;
DECLARE i DEFAULT 0;
DECLARE ctimestamp DEFAULT 0;
SELECT COUNT(*) FROM communication INTO commRowCount;
SET i = 0;
WHILE i < commRowCount DO
SELECT timestamp INTO ctimestamp FROM communication c
SELECT * FROM movement m
WHERE m.vID = c.fromID && m.timestamp <= R.timestamp
END$$
DELIMITER ;
但我知道那是完全错误的。
唯一的方法是游标吗?我在互联网上的任何地方都找不到这样的例子,而且我对 SQL.
中的程序完全陌生任何指导将不胜感激,谢谢!!
让我们看看我是否可以使用光标为您指明正确的方向:
delimiter $$
create procedure findClosestTimeStamp()
begin
-- Variables to hold values from the communications table
declare cFromId int;
declare cTimeStamp datetime;
-- Variables related to cursor:
-- 1. 'done' will be used to check if all the rows in the cursor
-- have been read
-- 2. 'curComm' will be the cursor: it will fetch each row
-- 3. The 'continue' handler will update the 'done' variable
declare done int default false;
declare curComm cursor for
select fromId, timestamp from communication; -- This is the query used by the cursor.
declare continue handler for not found -- This handler will be executed if no row is found in the cursor (for example, if all rows have been read).
set done = true;
-- Open the cursor: This will put the cursor on the first row of its
-- rowset.
open curComm;
-- Begin the loop (that 'loop_comm' is a label for the loop)
loop_comm: loop
-- When you fetch a row from the cursor, the data from the current
-- row is read into the variables, and the cursor advances to the
-- next row. If there's no next row, the 'continue handler for not found'
-- will set the 'done' variable to 'TRUE'
fetch curComm into cFromId, cTimeStamp;
-- Exit the loop if you're done
if done then
leave loop_comm;
end if;
-- Execute your desired query.
-- As an example, I'm putting a SELECT statement, but it may be
-- anything.
select *
from movement as m
where m.vID = cFromId and m.timeStamp <= cTimeStamp
order by timestampdiff(SECOND, cTimeStamp, m.timeStamp)
limit 1;
end loop;
-- Don't forget to close the cursor when you finish
close curComm;
end $$
delimiter ;
参考文献: