我的架构中有三个表:一个主表和两个引用表。 用户将搜索词(字符串)从AJAX传递到php到sql。
一个字符串查询很简单。两个或三个字符串查询(用逗号分隔,变成数组)要复杂得多......至少对我来说。我们的想法是搜索和过滤那些,因此每个返回必须包含 BOTH 字符串。不幸的是,这证明是困难的。它正在返回我想要的内容,但是当它是第一个或第二个列出 TWICE 的字符串时它也会返回。
这是我的代码:
SELECT DISTINCT a.document_id
FROM main a
INNER JOIN locations c
ON a.document_id = c.document_id
AND (c.street_address ILIKE any (array['%Benton%', '%Park%'])
OR c.location_name ILIKE any (array['%Benton%', '%Park%']) )
INNER JOIN names d ON a.document_id = d.document_id
AND (d.last_name ILIKE any (array['%Benton%', '%Park%'])
OR d.first_name ILIKE any (array['%Benton%', '%Park%']) )
AND (a.document_id ILIKE any (array['%Benton%', '%Park%']) )
OR a.title ILIKE any (array['%Benton%', '%Park%'])
OR a.description ILIKE ANY (array['%Benton%', '%Park%'])
GROUP BY a.document_id HAVING COUNT(*) > 2
ORDER BY a.document_id;
这里有更好的方法吗?
答案 0 :(得分:0)
@eurotrash - 你的问题实际上给了我一个想法。答案不仅在SQL中,而且在PHP循环中。我无法为每个查询加入所有表,因此我必须根据命中计数过滤哪些搜索。这是我的解决方案:
function searchArray($a, $b) {
$cnt = count($a);
$sqlArr = array();
$lastOne = end($b);
$valCnt = 0;
$qArr = array();
foreach ($b as $x => $x_value) {
$valCnt++;
$docCnt = $a[$x]['doccount'];
$LocCnt = $a[$x]['loccount'];
$PeepCnt = $a[$x]['namecount'];
$val = pg_escape_string($x_value);
$brac = "'%" . pg_escape_string($val) . "%'";
$haveCnt = "";
if ($docCnt == 0 && $LocCnt == 0 && $PeepCnt == 0) {
return;
}
$haveCnt = sprintf("GROUP BY t.document_id HAVING COUNT(*) > $cnt - 1");
$andOR = "";
$cntZero = array_filter($a[$x], function($value) {
return $value > 0;
});
$cntTheCnt = count($cntZero) >= 2 ? true : false;
if ($cntTheCnt == false) {
$andOR = "WHERE";
} else {
$andOR = "AND";
}
$subQuery = sprintf(" SELECT DISTINCT a$valCnt.document_id"
. " FROM archive_main a$valCnt");
$locJoin = sprintf(" INNER JOIN archive_locations f$valCnt"
. " ON a$valCnt.document_id = f$valCnt.document_id");
$locFind = sprintf(" %s f$valCnt.street_address ILIKE %s"
. " OR f$valCnt.location_name ILIKE %s ", $andOR, $brac, $brac);
$nameJoin = sprintf(" INNER JOIN archive_names b$valCnt"
. " ON a$valCnt.document_id = b$valCnt.document_id");
$nameFind = sprintf(" %s (b$valCnt.last_name ILIKE %s"
. " OR b$valCnt.first_name ILIKE %s) ", $andOR, $brac, $brac);
$nameFind .= "OR (FORMAT('%s %s', b$valCnt.first_name, b$valCnt.last_name) ILIKE $brac)";
$whereDoc = sprintf(" %s a$valCnt.document_id ILIKE %s"
. " OR a$valCnt.title ILIKE %s"
. " OR a$valCnt.description ILIKE %s", $andOR, $brac, $brac, $brac);
$find = "";
$union = "";
$joins = "";
if ($LocCnt != 0) {
$find .= $locFind;
$joins .= $locJoin;
}
if ($PeepCnt != 0) {
$find .= $nameFind;
$joins .= $nameJoin;
}
if ($docCnt != 0) {
$find .= $whereDoc;
}
if ($x_value != $lastOne) {
$union .= sprintf(" UNION ALL ");
} else {
$union .= sprintf("");
}
array_push($qArr, $subQuery, $joins, $find, $union);
}
$boom = implode(' ', $qArr);
$mainQuery = sprintf("SELECT DISTINCT t.document_id FROM (%s) as t %s
order by t.document_id;", $boom, $haveCnt);
$sql = pg_query($mainQuery);
if (!$sql) {
$errrormsge = pg_last_error();
print_r("$errrormsge - An error occurred during your query.");
exit;
}
return($sql);
}
效果很好。