搜索第一个,中间名和姓氏的所有组合

Xty*_*83a 5 mysql sql

在我的数据库中有一个名为的表author,其中有4列:

  • AUTHORID
  • 名字
  • 中间名字

例如,用户正在搜索Edgar Allan Poe.在我们的表中,Edgar Allan Poe保存为:firstName - Edgar,middleName - Allan和lastName - Poe.这个查询非常简单.但是如何编写一个不仅与Edgar Allan Poe相匹配的查询,还包括与Poe Allan Edgar,Edgar Poe,Allan Poe,Edgar Allan,Allan Edgar Poe匹配的查询,而不是自己编写所有这些可能的组合?此外,当用户搜索时,他/她完全搜索"Edgar Allan Poe"或"Poe Allan Edgar",而不是在单独的字段中搜索.

too*_*ice 2

请尝试以下操作...

DROP PROCEDURE IF EXISTS SimilarNames;
DELIMITER //
    CREATE PROCEDURE SimilarNames( authorFullName VARCHAR( 250 ) )
    BEGIN
        SET @authorFullNameCommad = CONCAT( '\'',
                                            REPLACE( authorFullName,
                                                     ' ',
                                                     '\', \'' ),
                                            '\'' );

        SET @selectStatementString := CONCAT( "SELECT authorID,",
                                              "       firstName,",
                                              "       middleName,",
                                              "       lastName ",
                                              "FROM author ",
                                              "WHERE ( ( firstName IN ( ",
                                              @authorFullNameCommad,
                                              " ) ) + ( middleName IN ( ",
                                              @authorFullNameCommad,
                                              " ) ) + ( lastName IN ( ",
                                              @authorFullNameCommad,
                                              " ) ) ) >=2;" );

        PREPARE selectStatement FROM @selectStatementString;
        EXECUTE selectStatement;
        DEALLOCATE PREPARE selectStatement;
   END //
DELIMITER ;
CALL SimilarNames( 'Edgar Allan Poe' );
Run Code Online (Sandbox Code Playgroud)

该解决方案首先创建一个PROCEDURE被调用的SimilarNames(在DROPping 任何现有版本之后PROCEDURE)。这PROCEDURE会将传递给它的名称(例如'Edgar Allan Poe')存储在参数变量中authorFullName

一旦开始,PROCEDURE首先将字符串转换为Edgar Allan Poe并将'Edgar', 'Allan', 'Poe'其存储在变量 中@authorFullNameCommad

然后该CONCAT()函数用于形成将产生结果的 SQL 语句文本。以下语句是authorFullName在哪里生成并存储在...Edgar Allan Poe@selectStatementString

SELECT authorID,
       firstName,
       middleName,
       lastName
FROM author
WHERE ( ( firstName IN ( 'Edgar', 'Allan', 'Poe' ) ) + ( middleName IN ( 'Edgar', 'Allan', 'Poe' ) ) + ( lastName IN ( 'Edgar', 'Allan', 'Poe' ) ) ) >=2;
Run Code Online (Sandbox Code Playgroud)

然后 SQL 语句是PREPAREd 和EXECUTEd,从而在调用时生成所需的列表PROCEDURE,这可以使用...来完成

CALL SimilarNames( 'Edgar Allan Poe' );
Run Code Online (Sandbox Code Playgroud)

请注意,您不必PROCEDURE在第一次这样做后声明。即以下内容可以正常工作......

CALL SimilarNames( 'Edgar Allan Poe' );
CALL SimilarNames( 'James Tiberius Kirk' );
Run Code Online (Sandbox Code Playgroud)

另请注意,此特定方法容易受到SQL 注入攻击。如果你愿意的话,我可以开发一个版本来防止这种情况发生——现在已经很晚了,我很快就要上床睡觉了。

我的声明针对使用以下脚本创建的示例数据集进行了测试......

CREATE TABLE author
(
    authorID     INT   NOT NULL AUTO_INCREMENT,
    firstName    VARCHAR( 50 ),
    middleName   VARCHAR( 50 ),
    lastName     VARCHAR( 50 ),
    PRIMARY KEY ( authorID )
);
INSERT INTO author ( firstName,
                     middleName,
                     lastName )
VALUES ( 'Edgar', 'Allan', 'Poe' ),
       ( 'Poe', 'Allan', 'Edgar' ),
       ( 'Edgar', 'Poe', '' ),
       ( 'Edgar', '', 'Poe' ),
       ( '', 'Edgar', 'Poe' ),
       ( 'Allan', 'Poe', '' ),
       ( 'Edgar', 'Allan', '' ),
       ( 'Allan', 'Edgar', 'Poe' ),
       ( 'Edgar', 'Allan', 'Allan' ),
       ( 'James', 'Tiberius', 'Kirk' ),
       ( 'Karl', 'Ignatius', 'von Bach' ),
       ( 'Edgar', 'Poe', 'xyz' ),
       ( 'Allanah', 'Poelsen', '' );
Run Code Online (Sandbox Code Playgroud)

结果正如我所料。

如果您有任何问题或意见,请随时发表评论。

进一步阅读

https://dev.mysql.com/doc/refman/5.7/en/call.html(关于MySQL的CALL声明)

https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_concat(关于MySQL的CONCAT()函数)

https://dev.mysql.com/doc/refman/5.7/en/create-procedure.html(关于MySQL的CREATE PROCEDURE声明)

https://dev.mysql.com/doc/refman/5.7/en/deallocate-prepare.html(关于MySQL的DEALLOCATE声明)

https://dev.mysql.com/doc/refman/5.7/en/stored-programs-defining.html(在MySQL的DELIMITER命令上)

https://dev.mysql.com/doc/refman/5.7/en/drop-procedure.html(关于MySQL的DROP PROCEDURE声明)

https://dev.mysql.com/doc/refman/5.7/en/execute.html(关于MySQL的EXECUTE声明)

https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_in(关于MySQL的IN运算符)

https://dev.mysql.com/doc/refman/5.7/en/prepare.html(关于MySQL的PREPARE声明)

https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_replace(关于MySQL的REPLACE()函数)

https://dev.mysql.com/doc/refman/5.7/en/set-statement.html(关于MySQL的SET声明)