2009-08-06 12 views
7

Mam zestaw 4 tabel, które chcę przeszukać. Każdy ma pełny indeks tekstowy. Czy zapytanie może wykorzystywać każdy indeks?MATERIAŁY mySQL w wielu tabelach

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; 

Oto moje zapytanie;

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

Oto moja konstrukcja SQL, a Użyłem powyższej kwerendy.

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 do osoby, która odpowiada na to pytanie ... .. poprawne – Dirk

+0

Przez sekundę wygląda na to, że ma najdłuższe zapytanie sql-query. –

+1

Edytowałem to mając nadzieję na znalezienie pytania ... czy to zagadka? –

Odpowiedz

22
  • Nie można zdefiniować indeksy pełnotekstowe (lub jakiegokolwiek indeksu) dla wielu tabel w MySQL. Każda definicja indeksu odwołuje się dokładnie do jednej tabeli. Wszystkie kolumny w danym indeksie pełnego tekstu muszą pochodzić z tej samej tabeli.

  • Kolumny nazwane jako argumenty funkcji MATCH() muszą być częścią pojedynczego indeksu pełnotekstowego. Nie można użyć pojedynczego połączenia do MATCH(), aby wyszukać wszystkie kolumny będące częścią wszystkich pełnotekstowych indeksów w bazie danych. tylko

  • pełnotekstowe indeksy indeks kolumny zdefiniowany CHAR, VARCHAR i TEXT typy danych.

  • Możesz zdefiniować indeks pełnotekstowy w każdej tabeli.

Przykład:

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

a następnie można napisać kwerendę, która korzysta z każdego odpowiedniego indeksu pełnotekstowego:

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; 
Powiązane problemy