2009-08-06 130 views
7

我有一套我想搜索的4個表。每個都有一個全文索引。一個查詢可以使用每個索引嗎?mySQL跨多個表的匹配

CREATE TABLE `categories` (
    `id` int(5) unsigned NOT NULL auto_increment, 
    `display_order` int(5) unsigned default NULL, 
    `name` varchar(64) default NULL, 
    `last_modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `order` (`display_order`), 
    FULLTEXT KEY `full_name` (`name`) 
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1; 

CREATE TABLE `host_types` (
    `id` int(5) unsigned NOT NULL auto_increment, 
    `category_id` int(5) unsigned default NULL, 
    `display_order` int(5) unsigned default NULL, 
    `name` varchar(64) default NULL, 
    `last_modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `order` (`category_id`,`display_order`), 
    FULLTEXT KEY `full_name` (`name`) 
) ENGINE=MyISAM AUTO_INCREMENT=13 DEFAULT CHARSET=latin1; 


CREATE TABLE `hosts` (
    `id` int(5) unsigned NOT NULL auto_increment, 
    `host_id` int(5) unsigned default NULL, 
    `display_order` int(5) unsigned default NULL, 
    `name` varchar(64) default NULL, 
    `last_modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `order` (`host_id`,`display_order`), 
    FULLTEXT KEY `full_name` (`name`) 
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; 


CREATE TABLE `products` (
    `id` int(11) unsigned NOT NULL auto_increment, 
    `host_id` int(5) unsigned default NULL, 
    `display_order` int(5) unsigned default NULL, 
    `uid` varchar(10) default NULL, 
    `name` varchar(128) default NULL, 
    `keywords` text, 
    `description` text, 
    `price` decimal(10,2) default NULL, 
    `quantity` int(11) unsigned default NULL, 
    `last_modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    FULLTEXT KEY `full_name` (`name`,`keywords`,`description`,`uid`) 
) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=latin1; 

這是我的查詢;

SELECT categories.name AS category, 
    categories.id AS category_id, 
    host_types.name AS host_type, 
    host_types.id AS host_type_id, 
    hosts.name AS host, 
    hosts.id AS host_id, 
    products.name as name, 
    products.id AS product_id, 
    products.keywords as keywords, 
    products.description AS description, 
    products.quantity AS quantity, 
    products.price AS price, 
    products.uid as catalogue, 
    MATCH(categories.name, host_types.name, hosts.name, products.name, 
     products.keywords, products.description, products.uid) 
     AGAINST('search term') as score 
FROM products 
LEFT JOIN hosts ON products.host_id = hosts.id 
LEFT JOIN host_types ON hosts.host_id = host_types.id 
LEFT JOIN categories ON host_types.category_id = categories.id 
WHERE MATCH(categories.name, host_types.name, hosts.name, products.name, 
      products.keywords, products.description, products.uid) 
     AGAINST('search term') 
ORDER BY score DESC; 
  • categories.name == FULLTEXT - 1
  • host_types.name == FULLTEXT - 2
  • hosts.name == FULLTEXT - 3
  • products.name,products.keywords, products.description,products.uid == FULLTEXT - 4

這裏是我的SQL結構,我用上面的查詢。

SELECT 
    categories.name AS category, 
    categories.id AS category_id, 
    host_types.name AS host_type, 
    host_types.id AS host_type_id, 
    hosts.name AS host, 
    hosts.id AS host_id, 
    products.name as name, 
    products.id AS product_id, 
    products.keywords as keywords, 
    products.description AS description, 
    products.quantity AS quantity, 
    products.price AS price, 
    products.uid as catalgue 
    MATCH(categories.name) AGAINST('search term') as cscore, 
    MATCH(host_types.name) AGAINST('search term') as htscore, 
    MATCH(hosts.name) AGAINST('search term') as hscore, 
    MATCH(products.name, products.keywords, products.description, products.uid) 
    AGAINST('search term') as score 
FROM products 
LEFT JOIN hosts ON products.host_id = hosts.id 
LEFT JOIN host_types ON hosts.host_id = host_types.id 
LEFT JOIN categories ON host_types.category_id = categories.id 
WHERE 
    MATCH(categories.name) AGAINST('search term') OR 
    MATCH(host_types.name) AGAINST('search term') OR 
    MATCH(hosts.name) AGAINST('search term') OR 
    MATCH(products.name, products.keywords, products.description, products.uid) 
    AGAINST('search term') 
ORDER BY score DESC 



     CREATE TABLE `categories` (
    `id` int(5) unsigned NOT NULL auto_increment, 
    `display_order` int(5) unsigned default NULL, 
    `name` varchar(64) default NULL, 
    `last_modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `order` (`display_order`), 
    FULLTEXT KEY `full_name` (`name`) 
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1; 

CREATE TABLE `host_types` (
    `id` int(5) unsigned NOT NULL auto_increment, 
    `category_id` int(5) unsigned default NULL, 
    `display_order` int(5) unsigned default NULL, 
    `name` varchar(64) default NULL, 
    `last_modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `order` (`category_id`,`display_order`), 
    FULLTEXT KEY `full_name` (`name`) 
) ENGINE=MyISAM AUTO_INCREMENT=13 DEFAULT CHARSET=latin1; 


CREATE TABLE `hosts` (
    `id` int(5) unsigned NOT NULL auto_increment, 
    `host_id` int(5) unsigned default NULL, 
    `display_order` int(5) unsigned default NULL, 
    `name` varchar(64) default NULL, 
    `last_modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `order` (`host_id`,`display_order`), 
    FULLTEXT KEY `full_name` (`name`) 
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; 


CREATE TABLE `products` (
    `id` int(11) unsigned NOT NULL auto_increment, 
    `host_id` int(5) unsigned default NULL, 
    `display_order` int(5) unsigned default NULL, 
    `uid` varchar(10) default NULL, 
    `name` varchar(128) default NULL, 
    `keywords` text, 
    `description` text, 
    `price` decimal(10,2) default NULL, 
    `quantity` int(11) unsigned default NULL, 
    `last_modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    FULLTEXT KEY `full_name` (`name`,`keywords`,`description`,`uid`) 
) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=latin1; 
+2

+50到誰回答這個問題......的人.. 。正確 – Dirk 2009-08-06 21:30:34

+0

第一次看起來像他有一個最長的sql查詢炫耀。 – 2009-08-06 21:32:00

+1

我編輯它希望能找到一個問題......這是一個謎語? – 2009-08-06 21:46:46

回答

22
  • 不能定義全文索引(或任何類型的指數)在多個表在MySQL。每個索引定義只引用一個表。給定全文索引中的所有列必須來自同一個表。

  • 作爲MATCH()函數參數命名的列必須是單個全文索引的一部分。您不能對MATCH()使用單個調用來搜索屬於數據庫中所有全文索引一部分的所有列。

  • 全文索引只索引用CHAR,VARCHARTEXT數據類型定義的索引列。

  • 您可以在每個表中定義全文索引。

例子:

CREATE TABLE categories (
    id SERIAL PRIMARY KEY, 
    name VARCHAR(100), 
    FULLTEXT INDEX ftcat (name) 
); 

CREATE TABLE host_types (
    id SERIAL PRIMARY KEY, 
    category_id BIGINT UNSIGNED, 
    name VARCHAR(100), 
    FULLTEXT INDEX ftht (name) 
); 

CREATE TABLE hosts (
    id SERIAL PRIMARY KEY, 
    host_id BIGINT UNSIGNED, 
    category_id BIGINT UNSIGNED, 
    name VARCHAR(100), 
    FULLTEXT INDEX fthost (name) 
); 

CREATE TABLE products (
    id SERIAL PRIMARY KEY, 
    name VARCHAR(100), 
    keywords VARCHAR(100), 
    uid VARCHAR(100), 
    description VARCHAR(100), 
    quantity INTEGER, 
    price NUMERIC(9,2), 
    host_id BIGINT UNSIGNED, 
    FULLTEXT INDEX ftprod (name, keywords, description, uid) 
); 

然後你就可以編寫使用每個相應的全文索引的查詢:

SELECT ... 
    MATCH(categories.name) AGAINST('search term') as cscore, 
    MATCH(host_types.name) AGAINST('search term') as htscore, 
    MATCH(hosts.name) AGAINST('search term') as hscore, 
    MATCH(products.name, products.keywords, products.description, products.uid) 
    AGAINST('search term') as score 
FROM products 
LEFT JOIN hosts ON products.host_id = hosts.id 
LEFT JOIN host_types ON hosts.host_id = host_types.id 
LEFT JOIN categories ON host_types.category_id = categories.id 
WHERE 
    MATCH(categories.name) AGAINST('search term') OR 
    MATCH(host_types.name) AGAINST('search term') OR 
    MATCH(hosts.name) AGAINST('search term') OR 
    MATCH(products.name, products.keywords, products.description, products.uid) 
    AGAINST('search term') 
ORDER BY score DESC;