困难的MySQL问题(关系和多行)

时间:2014-01-30 10:35:45

标签: mysql database relational-database

我有一个很难的mysql问题。我有一个数据库,将关键字与案例匹配,简化:

TABLE cases (id)
TABLE keywords (id)
TABLE cases_keywords (case, keyword)

所以我可以在案例A中使用关键字Y和Z,我可以在案例B中使用关键字X和Y.这在case_keywords中给出了四行:

(A, Y)
(A, Z)
(B, X)
(B, Y)

问题:

我在我的网站上搜索,用户输入要搜索的关键字。我希望结果在找到所有关键字时显示匹配项。因此,当用户在Y和Z中键入关键字时,仅出现案例A(因为案例B没有关键字Z)。但是当用户仅将Y作为关键字时,该网站同时显示A和B(因为它们都有关键字Y)。

所以我通过PHP知道查询是动态的,最大的问题是匹配多个关键字...假设我想匹配2个关键字:Y和Z结果:案例A。

如何将其编入查询?如何在多行上匹配?

SELECT C.id FROM cases C JOIN cases_keywords CK ON CK.case = C.id WHERE CK.keyword = Y AND CK.keyword = Z

上面没有用,所以我尝试了WHERE C.case IN(),但我也被困在那里......

有人请帮帮我

2 个答案:

答案 0 :(得分:1)

这里有2条建议。

第一个必须动态构建,效率不高,但很容易理解。

SELECT C.id 
FROM cases C 
JOIN cases_keywords CK1 ON CK1.case = C.id AND CK1.keyword = Y
JOIN cases_keywords CK2 ON CK2.case = C.id AND CK2.keyword = Z

效率更高,可以非动态构建: -

SELECT C.id, COUNT(CK.keyword) AS KeywordCount
FROM cases C 
JOIN cases_keywords CK ON CK.case = C.id
WHERE CK.keyword IN ('Y', 'Z')
GROUP BY C.id
HAVING KeywordCount = 2

答案 1 :(得分:0)

如果您可以使用MyISAM存储引擎(或者可能是MySQL 5.6中的InnoDB),您可以使用全文索引执行以下操作(然后允许您拥有实际上是短语的关键字):

CREATE TABLE cases (id INT AUTO_INCREMENT PRIMARY KEY,
                    name VARCHAR(10) NOT NULL) Engine = MyISAM;

CREATE TABLE keywords (id INT AUTO_INCREMENT PRIMARY KEY,
                       word VARCHAR(10) NOT NULL) Engine = MyISAM;

ALTER TABLE keywords ADD FULLTEXT INDEX (word);

CREATE TABLE cases_keywords (`case` INT,
                             keyword INT,
                             PRIMARY KEY (`case`,keyword)) Engine = MyISAM;

INSERT INTO cases VALUES (1,'Alpha'),(2,'Beta');
INSERT INTO keywords VALUES (1,'Xylophone'),(2,'Yaks'),(3,'Zebra');

INSERT INTO cases_keywords VALUES (1,2),(1,3),(2,1),(2,2);

SELECT `cases`.name, COUNT(keywords.id) AS matches
FROM  `cases` 
JOIN cases_keywords
  ON cases_keywords.case = `cases`.id
JOIN keywords
  ON keywords.id = cases_keywords.keyword
WHERE MATCH(word) AGAINST ('(Yaks Zebra) ("Yaks Zebra") (+Yaks* +Zebra*)' IN BOOLEAN MODE)
GROUP BY `cases`.id
ORDER BY matches DESC

使用SQLFiddle:http://sqlfiddle.com/#!2/49c19/2

显然,您可以调整全文搜索以按您的需要工作,但我们使用以下BOOLEAN MODE搜索来执行以下操作(符合我们的要求):

(Yaks Zebra) -> matches any occurence in the `word` column of Yak or Zebra
("Yaks Zebra") -> matches the whole phrase "Yaks Zebra" in the `word` column
(+Yaks* +Zebra*) -> requires both Yaks and Zebra to be in the `word` column, but
                    also allows extra characters after each of those words...