如何在 mysql 的 UDF 中创建两个循环

Posted

技术标签:

【中文标题】如何在 mysql 的 UDF 中创建两个循环【英文标题】:How to make TWO loops in a UDF at mysql 【发布时间】:2020-04-18 09:03:08 【问题描述】:

类似于***Posting 我想计算由TITLE1 和TITLE2 组成的m x n 矩阵的Levenshtein 距离。

我的 Levenshtein Functions 工作正常,来自这里:LD 但我的问题是如何在 UDF 中循环遍历 m x n

结果应该是一个包含m x n 行的表,其中包含 LD、TITLE1 和 TITLE2。

我已经这样做了 - 但我总是出错

     1338 Cursor Declaration after Handler Declaration

我的 UDF 如下所示:

  BEGIN  
       DECLARE bDone INT;
       DECLARE bDone1 INT;

       DECLARE var2 varCHAR(255);    -- or approriate type
       DECLARE Var1 INT;
       DECLARE c1Var1 VARCHAR(250);

       DECLARE curs CURSOR FOR  SELECT recid as BIOTIrecid, replace(replace(BIOGRAPHYTITLE," [in SCOPUS]",""),"[SIMILAR]","") as bioti FROM BIO ;
       DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
       DECLARE curs1 CURSOR FOR  SELECT trim(concat(scopus.Titel," ",scopus.Untertitel)) as scopusti FROM scopus ;
       DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;

       DROP  TABLE IF EXISTS LDResults;
        CREATE TABLE `LDResults` (
           `BIOGRAPHYTITLE` varchar(255) DEFAULT NULL,
           `recid` int(11) NOT NULL AUTO_INCREMENT,
           `BIOTIrecid` int(11) default NULL,
           `LD` varchar(255) DEFAULT NULL,
           `ScopusTI` varchar(255) DEFAULT NULL,
           PRIMARY KEY (`recid`)
        ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

        OPEN curs1;

        SET bDone1 = 0;
        #---------------- run all rows for scopusti
        REPEAT
            FETCH curs1 into c1var1;

        #-----------------------------------------
            OPEN curs;

            SET bDone = 0;
            #----- run all COLUMNs for biographytitle
            REPEAT
                FETCH curs INTO var1, var2;
                INSERT INTO LDResults (`BIOGRAPHYTITLE`, `BIOTIrecid`, `LD`, `ScopusTI`) VALUES (var2, var1, LEVENSHTEIN(var2,c1var1), c1var1);
            UNTIL bDone END REPEAT;
        #--------------------------------------------
        CLOSE curs;

        UNTIL bDone1 END REPEAT;


       CLOSE curs1;
       SELECT * FROM LDResults;
     END

我解决这个问题的方法是复杂的,还是可以通过更快更好的解决方案来完成?

感谢所有建议。

编辑: 我可以在这里使用柜台:任何 cmets?

     BEGIN  
        -- DECLARE bDone INT;
        -- DECLARE bDone1 INT;

        DECLARE i INT;

       DECLARE var2 varCHAR(255);    -- or approriate type
       DECLARE Var1 INT;
       DECLARE cVar1 VARCHAR(250);

       DECLARE curs1 CURSOR FOR  SELECT trim(concat(t.Titel," ",t.Untertitel)) as scopusti FROM tscopus t ;
       DECLARE curs CURSOR FOR  SELECT recid as BIOTIrecid, replace(replace(BIOGRAPHYTITLE," [in SCOPUS]",""),"[SIMILAR]","") as bioti FROM tBIO ;
       DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
       #DECLARE curs1 CURSOR FOR  SELECT trim(concat(t.Titel," ",t.Untertitel)) as scopusti FROM tscopus t ;
       #DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;

       DROP  TABLE IF EXISTS LDResults;
        CREATE TABLE `LDResults` (
       `BIOGRAPHYTITLE` varchar(255) DEFAULT NULL,
       `recid` int(11) NOT NULL AUTO_INCREMENT,
       `BIOTIrecid` int(11) default NULL,
       `LD` varchar(255) DEFAULT NULL,
       `ScopusTI` varchar(255) DEFAULT NULL,
       PRIMARY KEY (`recid`)
        ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;


        OPEN curs1;
        SET i = 0;

        SET bDone1 = 0;
        -- ---------------- run all rows for scopusti
        REPEAT
            FETCH curs1 into cvar1;

         set i=(i+1);
        -- -----------------------------------------
            OPEN curs;

            SET bDone = 0;
            -- ----- run all COLUMNs for biographytitle
            REPEAT
                FETCH curs INTO var1, var2;
                INSERT INTO LDResults (`BIOGRAPHYTITLE`, `BIOTIrecid`, `LD`, `ScopusTI`) VALUES (var2, var1, LEVENSHTEIN(var2,cvar1), cvar1);
            UNTIL bDone END REPEAT;
        -- --------------------------------------------
        CLOSE curs;

        UNTIL (i >= 2) END REPEAT;


       CLOSE curs1;
       SELECT * FROM LDResults;
     END

【问题讨论】:

【参考方案1】:

我的意思是你可以通过下一个方法使用 CROSS JOIN 在你的代码中没有循环。 CROSS JOIN 按定义返回两个表行结果的乘积。 因此,您可以使用此结果,并在进行一些数据操作后将结果插入到新表中,例如:

DROP  TABLE IF EXISTS LDResults;
CREATE TABLE `LDResults` (
   `BIOGRAPHYTITLE` varchar(255) DEFAULT NULL,
   `recid` int(11) NOT NULL AUTO_INCREMENT,
   `BIOTIrecid` int(11) default NULL,
   `LD` varchar(255) DEFAULT NULL,
   `ScopusTI` varchar(255) DEFAULT NULL,
   PRIMARY KEY (`recid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO LDResults (`BIOGRAPHYTITLE`, `BIOTIrecid`, `LD`, `ScopusTI`)
SELECT bioti, BIOTIrecid, LEVENSHTEIN(bioti,scopusti), scopusti
FROM (
    SELECT 
        replace(replace(BIO.BIOGRAPHYTITLE," [in SCOPUS]",""),"[SIMILAR]","") as bioti,
        BIO.recid as BIOTIrecid,
        trim(concat(scopus.Titel," ",scopus.Untertitel)) as scopusti 
    FROM scopus
    CROSS JOIN BIO
) tbl;

【讨论】:

以上是关于如何在 mysql 的 UDF 中创建两个循环的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Hive 中创建 UDF

在 for 循环中使用 udf 在 Pyspark 中创建多个列

如何在 Redshift 中创建自定义聚合 UDF 函数?

如何在 BigQuery 中创建 UDF?例程名称缺失数据集

如何在 Spark 中创建 UDF 以支持自定义谓词

如何使用 python 在 HIVE 中创建 UDF 进行时间戳转换