MariaDB 存储过程陷入与同一 Join 行匹配的循环中

问题描述 投票:0回答:1

我需要匹配两个表中的行。匹配完成后,我会删除匹配的行并继续匹配后续匹配。

我的存储过程一直工作到某个匹配,然后迭代同一匹配,直到我的 while 循环达到其行限制。我设置此行限制是因为 SP 之前无限循环。

我不确定我做错了什么。

DELIMITER //
CREATE PROCEDURE MatchTransactions()
BEGIN
    -- Declare variables at the beginning
    DECLARE rows_deleted INT DEFAULT 1;
    DECLARE min_rows INT;

    -- Create temporary tables
    CREATE TEMPORARY TABLE TempA AS SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS row_num FROM SA_A;
    CREATE TEMPORARY TABLE TempB AS SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS row_num FROM SA_B;

    -- Get the minimum number of rows between the two tables
    SELECT LEAST((SELECT COUNT(*) FROM TempA), (SELECT COUNT(*) FROM TempB)) INTO min_rows;

    -- Create a table to store the matches
    CREATE TABLE Matches (A_row INT, B_row INT, A_ID INT, B_ID INT);


    -- Loop until no more matches are found or the number of iterations exceeds the minimum number of rows
    WHILE rows_deleted > 0 AND (SELECT COUNT(*) FROM Matches) < min_rows DO
        -- Reset rows_deleted
        SET rows_deleted = 0;

        -- Start a new transaction
        START TRANSACTION;

        -- Find a match
        SELECT A.row_num, B.row_num, A.A_ID, B.B_ID INTO @match_A, @match_B, @A_id, @B_id
        FROM TempA AS A
        INNER JOIN TempB AS B 
        ON A.ENTRY_DATE = B.TRANSACTION_DATE 
        AND A.TRANSACTION_AMOUNT = B.TRANSACTION_AMOUNT 
        AND A.CREDIT_DEBIT = B.CREDIT_DEBIT 
        AND A.ACCOUNT = B.PRIMARY_ACCOUNT 
        AND ABS(TIMEDIFF(A.TIME, B.TIME)) <= '00:00:15'
        LIMIT 1;

        -- If a match was found, delete it from both tables and add it to the Matches table
        IF @A_id IS NOT NULL AND @B_id IS NOT NULL THEN
            DELETE FROM TempA WHERE A_ID = @A_id;
            DELETE FROM TempB WHERE B_ID = @B_id;

            INSERT INTO Matches(A_row, B_row, A_ID, B_ID) VALUES (@match_A, @match_B, @A_id, @B_id);

            -- Get the number of rows deleted in this iteration
            SET rows_deleted = ROW_COUNT();
        END IF;

        -- Commit the transaction
        COMMIT;
    END WHILE;

    -- Select the matches
    SELECT * FROM Matches;

    -- Drop the temporary tables and the Matches table
    DROP TEMPORARY TABLE IF EXISTS TempA;
    DROP TEMPORARY TABLE IF EXISTS TempB;
    DROP TABLE IF EXISTS Matches;
END//
DELIMITER ;

如前所述,我在 WHILE 循环上添加了 min_rows 约束以强制其终止,无论如何,我的 Matches 表中的理论最大行数最多应该等于 min_rows。

sql stored-procedures mariadb
1个回答
0
投票

找到匹配项后,将其从两个源表中删除,然后将其添加到

Matches
表中。没错,但是当有些行无法匹配时会发生什么,因此 while 条件
(SELECT COUNT(*) FROM Matches) < min_rows
始终满足?

如果发生这种情况,

Matches
表中的行数将永远不会至少等于变量
min_rows
- 因此它会无限运行。

当未找到匹配项时,也许您应该减少变量的值

min_rows

getting stuck on the same row
的原因完美证实了我所说的。存储过程找不到该行的匹配项,因此它继续运行,因为
(SELECT COUNT(*) FROM Matches) < min_rows
的结果是
TRUE

© www.soinside.com 2019 - 2024. All rights reserved.