2009-08-06 22 views
7

Ho un set di 4 tabelle che voglio cercare attraverso. Ognuno ha un indice di testo completo. Una query può utilizzare ogni indice?mySQL MATCH su più tabelle

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; 

Ecco la mia richiesta;

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

Ecco la mia struttura di SQL, e Ho usato la query precedente.

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 alla persona che risponde a questa domanda ... .. . correttamente – Dirk

+0

Per un secondo sembra che stia facendo uno show-off con query sql più lunga. –

+1

L'ho modificato sperando di trovare una domanda ... è un indovinello? –

risposta

22
  • Non è possibile definire gli indici full-text (o qualsiasi tipo di indice) su più tabelle in MySQL. Ogni definizione di indice fa riferimento esattamente a una tabella. Tutte le colonne in un indice di testo completo devono essere dalla stessa tabella.

  • Le colonne denominate come argomenti della funzione MATCH() devono far parte di un singolo indice di testo completo. Non è possibile utilizzare una singola chiamata a MATCH() per cercare tutte le colonne che fanno parte di tutti gli indici di testo completo nel database.

  • Indici a testo intero solo colonne indice definite con CHAR, VARCHAR e TEXT tipi di dati.

  • È possibile definire un indice di testo completo in ciascuna tabella.

Esempio:

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) 
); 

E poi è possibile scrivere una query che utilizza ogni rispettivo indice full-text:

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;