MySQL PHP若语句表中不存在表中的关键字短语,则显示结果

MySQL PHP若语句表中不存在表中的关键字短语,则显示结果,php,mysql,full-text-search,Php,Mysql,Full Text Search,我有两张表格:句子,否定句 Sentences.sentence Sample Data ============================= - university lab on campus - laboratory designs - lab coats - math lab - methane production - meth lab Negatives.negphrase Sample Data ================================

我有两张表格:句子,否定句

Sentences.sentence Sample Data
=============================

 - university lab on campus
 - laboratory designs
 - lab coats
 - math lab
 - methane production
 - meth lab

Negatives.negphrase Sample Data
======================================

 - coats
 - math lab
 - meth

Desired Result Set
==================

 - university lab on campus
 - laboratory designs
 - methane production
我想选择列句子。句子中不包含任何记录的否定词。否定短语

句子中有20万条记录,否定词中有50万条记录

Sentences.sentence Sample Data
=============================

 - university lab on campus
 - laboratory designs
 - lab coats
 - math lab
 - methane production
 - meth lab

Negatives.negphrase Sample Data
======================================

 - coats
 - math lab
 - meth

Desired Result Set
==================

 - university lab on campus
 - laboratory designs
 - methane production
我尝试使用我的另一个问题的结果,但数据库超时:

SELECT Sentences.sentence
FROM Sentences, Negatives
GROUP BY Sentences.sentence
HAVING (((Max(InStr(" " & sentence & " "," " & negphrase & " ")))=0));
我的答案

因此,我将给Richard b/c一个正确的答案。他的解决方案适用于较小的记录集,但不适用于较大的记录集。下面是我用来将所有否定关键字放入一个数组的PHP代码,然后使用UPDATE子句循环该数组,在句子表中标记一个新列“negmatch”。我将在另一个WHERE子句中使用它来选择句子

我只需要对所有否定短语运行一次代码,然后当我添加额外的关键字时,我使用相同的代码,但没有循环来再次搜索句子(下面没有显示代码)。代码需要6.5分钟来循环2800个UPDATE子句,因此初始加载相当长,但一旦完成,就不必再次加载

<?php
$mysqli = new mysqli("localhost", "myuser", "myuserpassword", "database");

/* check connection */
if ($mysqli->connect_errno) {
    printf("Connect failed: %s\n", $mysqli->connect_error);
    exit();
}

if ($result = $mysqli->query("SELECT negphrase FROM negatives")) {  
    $row_cnt = $result->num_rows;
    printf("Negative keywords have %d rows.\n", $row_cnt); //print count of rows

    while($row = $result->fetch_assoc()){ //loop through all results by row
        foreach( $row  AS $value ) {
        $negative[] = $value;
    }
}


    /* free result set */
    $result->close();

    $data = array_values($negative); // get only values
    $data = array_filter($data);
    $datacount = 1;
    foreach($data as $val) { //loop through array to build MySQL WHERE clause


            $updatequery = "UPDATE Sentences SET negmatch=1 WHERE sentence REGEXP '[[:<:]]" . trim($val) . "[[:>:]]'";
            echo $updatequery  . "<br />";

            mysqli_query($mysqli,$updatequery) or die (mysqli_error($mysqli));
            echo $datacount . " " . trim($val) ."<br />";
            $datacount++;

        }

}
$mysqli->close();


    unset($result, $row, $mysqli,$value,$negative,$data,$val,$updatequery,$datacount,$row_cnt);


确保两列都正确索引

使用负左联接,这将仅返回Senteces表中与基于规则的负表不匹配的行

select * from Sentences s 
left join Negatives n 
on (concat(" ",s.sentence," ") like concat("% ",n.negphrase," %"))
where n.negphrase is null
测试数据如下

CREATE TABLE IF NOT EXISTS `Negatives` (
  `negphrase` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `Negatives` (`negphrase`) VALUES
('coats'),
('math lab'),
('meth');

CREATE TABLE IF NOT EXISTS `Sentences` (
  `sentence` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `Sentences` (`sentence`) VALUES
('university lab on campus'),
('laboratory designs'),
('lab coats'),
('math lab'),
('methane production'),
('meth lab'),
('testing sentence');  

嗨,付款人,谢谢你的回复。不幸的是,这只返回第一行句子的结果集。句子x 50k行,然后转到第二行句子。句子并返回另外50k行,以此类推。它还需要从句子到否定的记录的完全匹配。我希望在句子中搜索否定词,如果有点击,不要显示该行。谢谢Richard。它完全适用于小记录集,但由于我的示例中记录的数量(200k个句子,50k个关键字)而超时。有没有一种方法可以加快速度,可能是创建一个只包含不匹配项的新表?然后,每次我在否定列表中添加一个新词时,该表都将被重新创建?您可以使用create table TEMPSEANCES作为select*from语句。这将克隆表。然后,如果您知道MySQL的一些过程扩展,比如,您可以编写一个for循环,它将遍历否定词中的短语,并从句子中删除所有匹配的行。复杂性仍然是O(n*m),其中n是句子数,m是短语数。如果你想进一步优化,你可以使用全文索引,或者你可以尝试类似Aho-Corasick的实现,但这将超出MySQL本身的能力。因此,在具有大型记录集的MySQL中,这几乎是不可能的,我觉得这很可笑。我的下一个方法是将所有Negatives.negPhase放在一个数组中,然后在该数组中循环并执行另一个查询,以创建一个包含所有句子的数组。如果它们与该negPhase匹配,则为sentenceID。在循环之后,我将更新名为negmatch的句子中的一列,并为每个匹配项将其设置为1。你知道如何用php编写代码吗?