在两个表上执行AND连接搜索

时间:2014-11-12 09:26:34

标签: mysql sql search

我有两张桌子

#keywords
content_id | keyword
-----------+----------
2          | lorem
6          | loremsis
6          | ipsum
6          | dolor

#tags
content_id | tag
-----------+----------
2          | amet
6          | lorem
6          | amet

注意,这两个表不能合并到一个表中。我想用AND连接和右侧LIKE运算符执行搜索。目前,该声明似乎是

SELECT content_id FROM (

  SELECT content_id FROM store_keywords
  WHERE keyword LIKE 'lorem%' OR keyword LIKE 'ipsum%'

  UNION ALL

  SELECT content_id FROM store_tags
  WHERE tag LIKE 'lorem%' OR tag LIKE 'ipsum%'

) s1
GROUP BY content_id
HAVING COUNT(*)='2'

那么搜索"lorem ipsum"时会得到什么?

#keywords
content_id | keyword
-----------+----------
2          | lorem
6          | loremsis
6          | ipsum

#tags
content_id | tag
-----------+----------
6          | lorem

这不适合HAVING COUNT(*)='2',可以使用>='2'修复。因此返回ID 6,因为它包含两个术语。但是在搜索"lorem odem"时我们会得到

#keywords
content_id | keyword
-----------+----------
2          | lorem
6          | loremsis

#tags
content_id | tag
-----------+----------
6          | lorem

符合HAVING子句但不包含任何结果"odem"

那么,是否有人对具有以下要求的陈述采取措施:

  • 必须找到搜索字词的所有字词( AND 连锁搜索)
  • 搜索是在两个表上执行的,可以包含两个表中的双精度和匹配项,但仅在一个表中

2 个答案:

答案 0 :(得分:1)

仍然无法理解您的描述,但查看您的项目,您可能想要

获取content_id,其中包含搜索字符串中的两个单词,可以是关键字或标签

正确?

然后你需要这个查询:

SELECT distinct t1.content_id FROM
(
  SELECT content_id FROM store_keywords
  WHERE keyword LIKE 'lorem%'
  UNION
  SELECT content_id FROM store_tags
  WHERE tag LIKE 'lorem%'
) t1
INNER JOIN
(
  SELECT content_id FROM store_keywords
  WHERE keyword LIKE 'ipsum%'
  UNION
  SELECT content_id FROM store_tags
  WHERE tag LIKE 'ipsum%'
) t2
ON t1.content_id = t2.content_id

答案 1 :(得分:0)

@ David162795答案只适用于某些搜索字词,但在现实生活中可能有十几个字词,所以我会试试临时表。我认为我的解决方案比许多INNER JOIN慢得多。因此,我将每个content_id与搜索词一起添加到临时表中。

CREATE TEMPORARY TABLE search (
    content_id INT UNSIGNED NOT NULL,
    term VARCHAR(50) NOT NULL,
    PRIMARY KEY (content_id, term)
);

INSERT IGNORE INTO search (content_id, term) SELECT content_id,'lorem' FROM store_keywords WHERE keyword LIKE 'lorem%';
INSERT IGNORE INTO search (content_id, term) SELECT content_id,'ipsum' FROM store_keywords WHERE keyword LIKE 'ipsum%';
INSERT IGNORE INTO search (content_id, term) SELECT content_id,'lorem' FROM store_tags WHERE tag LIKE 'lorem%';
INSERT IGNORE INTO search (content_id, term) SELECT content_id,'ipsum' FROM store_tags WHERE tag LIKE 'ipsum%';

现在可以从ID中清除表格,其中出现的次数少于术语的数量

DELETE t1
FROM search t1
INNER JOIN (
    SELECT content_id FROM search GROUP BY content_id HAVING COUNT(*)<2
) t2 ON t1.content_id=t2.content_id;

或直接在SELECT中使用该表

SELECT t1.*
FROM store_content t1 INNER JOIN (
    SELECT content_id FROM search GROUP BY content_id HAVING COUNT(*)>=2
) t2 ON t1.id=t2.content_id;