[英]mySQL join three tables and search on several keywords found in one table
我試圖通過避免包含相同單詞的多個記錄來限制數據庫的大小,因此我建立了兩個表,用於將關鍵字與其他表中的行相關聯。
例如,我們使用以下搜索輸入:“找到我”
希望得到什么,這是product_id = 106中的product_name。我可以僅搜索產品名稱嗎? 否,因為產品可以與其他關鍵字(不屬於product_name的一部分)相關聯。
表格:ec_products
product_id | product_name | is_deleted
---------------------------------------------
106 | some product | 0
表格:ec_keywords_index
word_id | keyword
---------------------------------------------
55 | find
61 | my
77 | product
表格:ec_keyword_relations
word_id | application_id | related_id
------------------------------------------------
55 | 1 | 106
61 | 1 | 106
77 | 1 | 106
因此,當我在搜索輸入中輸入“ find my”時,我現在想要的是:
這是到目前為止我已經嘗試過的方法(並且我知道我暫時還沒有一個可行的解決方案):
$searchInput = 'find my';
$keywords = explode(' ', $searchInput);
$keyword_count = count($keywords);
$n = 1;
$query = '';
foreach($keywords as $keyword) {
if ($n !== $keyword_count) {
$query_ext = ' AND ';
} else {
$query_ext = '';
}
$query .= "(ec_keywords_index.keyword LIKE '%$keyword%')" . $query_ext;
++$n;
}
$query = "
SELECT
ec_products.product_name
FROM
ec_products
LEFT JOIN ec_search_word_relations
ON ec_keyword_relations.related_id = ec_products.product_id
LEFT JOIN ec_keywords_index
ON ec_keywords_index.word_id = ec_keyword_relations.word_id
WHERE
($query)
AND
ec_products.is_deleted = '0'
AND
ec_keyword_relations.application_id = '1'
GROUP BY
ec_products.product_id
ORDER BY
ec_products.product_name ASC
LIMIT
100";
$stmt = $mysqli->prepare($query);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($name);
while ($stmt->fetch()) {
echo $name;
}
更新:
經過一番擺弄之后,我想出了可以按預期工作的解決方案。 (就性能而言)是好的還是壞的解決方案?
$searchInput = 'find my';
$keywords = explode(' ', $searchInput);
$keyword_count = count($keywords);
$n = 1;
$where_query = '';
$having_query = '';
foreach($keywords as $keyword) {
if ($n != $keyword_count) {
$w_query_ext = ' OR ';
$h_query_ext = ' AND ';
} else {
$w_query_ext = '';
$h_query_ext = '';
}
$where_query .= "ec_keywords_index.keyword LIKE '%" . $keyword . "%'" . $w_query_ext;
$having_query .= "related_keywords LIKE '%" . $keyword . "%'" . $h_query_ext;
++$n;
}
$query = "
SELECT
ec_products.product_name,
GROUP_CONCAT(' ', ec_keywords_index.keyword) AS 'related_keywords'
FROM
ec_products,
ec_keywords_index
LEFT JOIN
ec_keyword_relations
ON ec_keyword_relations.word_id = ec_keywords_index.word_id
WHERE ($where_query)
AND ec_products.product_id = ec_keyword_relations.related_id
AND ec_keyword_relations.application_id = '1'
AND ec_products.is_deleted = '0'
GROUP BY
ec_products.product_name
HAVING
($having_query)
LIMIT
100";
$stmt = $mysqli->prepare($query);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($name);
while ($stmt->fetch()) {
echo $name;
}
上面的示例輸出如下查詢:
SELECT
ec_products.product_name,
GROUP_CONCAT(' ', ec_keywords_index.keyword) AS 'related_keywords'
FROM
ec_products,
ec_keywords_index
LEFT JOIN
ec_keyword_relations
ON ec_keyword_relations.word_id = ec_keywords_index.word_id
WHERE (ec_keywords_index.keyword LIKE '%find%' OR ec_keywords_index.keyword LIKE '%my%')
AND ec_products.product_id = ec_keyword_relations.related_id
AND ec_keyword_relations.application_id = '1'
AND ec_products.is_deleted = '0'
GROUP BY
ec_products.product_name
HAVING
(related_keywords LIKE '%find%' AND related_keywords LIKE '%my%')
LIMIT
100
我正在使用GROUP_CONCAT創建一個包含與產品相關的所有關鍵字的列,然后使用我的WHERE子句僅選擇在搜索字符串中實際找到的關鍵字...然后使用HAVING子句在該列中進行搜索使用GROUP_CONCAT構建。
擁有示例的答案:
經過一番擺弄之后,我想出了可以按預期工作的解決方案。 我不知道這是否是最佳做法,但它就像一個魅力。
$searchInput = 'find my';
$keywords = explode(' ', $searchInput);
$keyword_count = count($keywords);
$n = 1;
$where_query = '';
$having_query = '';
foreach($keywords as $keyword) {
if ($n != $keyword_count) {
$w_query_ext = ' OR ';
$h_query_ext = ' AND ';
} else {
$w_query_ext = '';
$h_query_ext = '';
}
$where_query .= "ec_keywords_index.keyword LIKE '%" . $keyword . "%'" . $w_query_ext;
$having_query .= "related_keywords LIKE '%" . $keyword . "%'" . $h_query_ext;
++$n;
}
$query = "
SELECT
ec_products.product_name,
GROUP_CONCAT(' ', ec_keywords_index.keyword) AS 'related_keywords'
FROM
ec_products,
ec_keywords_index
LEFT JOIN
ec_keyword_relations
ON ec_keyword_relations.word_id = ec_keywords_index.word_id
WHERE ($where_query)
AND ec_products.product_id = ec_keyword_relations.related_id
AND ec_keyword_relations.application_id = '1'
AND ec_products.is_deleted = '0'
GROUP BY
ec_products.product_name
HAVING
($having_query)
LIMIT
100";
$stmt = $mysqli->prepare($query);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($name);
while ($stmt->fetch()) {
echo $name;
}
上面的示例輸出如下查詢:
SELECT
ec_products.product_name,
GROUP_CONCAT(' ', ec_keywords_index.keyword) AS 'related_keywords'
FROM
ec_products,
ec_keywords_index
LEFT JOIN
ec_keyword_relations
ON ec_keyword_relations.word_id = ec_keywords_index.word_id
WHERE (ec_keywords_index.keyword LIKE '%find%' OR ec_keywords_index.keyword LIKE '%my%')
AND ec_products.product_id = ec_keyword_relations.related_id
AND ec_keyword_relations.application_id = '1'
AND ec_products.is_deleted = '0'
GROUP BY
ec_products.product_name
HAVING
(related_keywords LIKE '%find%' AND related_keywords LIKE '%my%')
LIMIT
100
我正在使用GROUP_CONCAT創建一個包含與產品相關的所有關鍵字的列,然后使用我的WHERE子句僅選擇在搜索字符串中實際找到的關鍵字...然后使用HAVING子句在該列中進行搜索使用GROUP_CONCAT構建。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.