10


6

検索したい4つのテーブルのセットがあります。 それぞれにフルテキストインデックスがあります。 クエリはすべてのインデックスを利用できますか?

CREATE TABLE `categories`(` id` int(5)符号なしNOT NULL auto_increment、 `display_order` int(5)符号なしデフォルトNULL、` name` varchar(64)デフォルトNULL、 `last_modified`タイムスタンプNOT NULLデフォルト更新時CURRENT_TIMESTAMP 、PRIMARY KEY( `id`)、UNIQUE KEY` order`( `display_order`)、FULLTEXT KEY` full_name`( `name`))ENGINE = MyISAM AUTO_INCREMENT = 6デフォルトCHARSET = latin1;

CREATE TABLE `host_types`(` id` int(5)符号なしNOT NULL auto_increment、 `category_id` int(5)符号なしデフォルトNULL、` display_order` int(5)符号なしデフォルトNULL、 `name` varchar(64)デフォルトNULL、更新時の `last_modified`タイムスタンプNOT NULLデフォルトCURRENT_TIMESTAMP、PRIMARY KEY(` id`)、UNIQUE KEY `order`(` category_id`、 `display_order`)、FULLTEXT KEY` full_name`( `name`)ENGINE = MyISAM AUTO_INCMENT = 13デフォルト文字= latin1;

CREATE TABLE `hosts`(` id` int(5)符号なしNOT NULL auto_increment、 `host_id` int(5)符号なしデフォルトNULL、` display_order` int(5)符号なしデフォルトNULL、 `name` varchar(64)デフォルトNULL、更新時の `last_modified`タイムスタンプNOT NULLデフォルトCURRENT_TIMESTAMP、PRIMARY KEY(` id`)、一意キー `order`(` host_id`、 `display_order`)、FULLTEXT KEY` full_name`( `name`) = 4デフォルト文字= latin1;

CREATE TABLE `products`(` id` int(11)符号なしNOT NULL auto_increment、 `host_id` int(5)符号なしデフォルトNULL、` display_order` int(5)符号なしデフォルトNULL、 `uid` varchar(10)デフォルトNULL、 `name` varchar(128)デフォルトNULL、` keywords`テキスト、 `description`テキスト、` price` decimal(10,2)デフォルトNULL、 `Quantity` int(11)符号なしデフォルトNULL、` last_modified`タイムスタンプNOT NULLデフォルトCURRENT_TIMESTAMP、更新時CURRENT_TIMESTAMP、PRIMARY KEY( `id`)、FULLTEXT KEY` full_name`( `name`、` keywords`、 `description`、` uid`)エンジン= MyISAM AUTO_INCREMENT = 14デフォルトCHARSET = latin1;

これが私の質問です。

SELECT categories.name ASカテゴリ、categories.id AS category_id、host_types.name AS host_type、host_types.id AS host_type_id、hosts.name ASホスト、hosts.id AS host_id、名前としてproducts.id、products.id AS product_id、productsキーワードとしてのキーワード、products.descriptionとしての説明、products.quantityとしての数量、products.priceとしての価格、catalog.としてのproducts.uid、MATCH(categories.name、host_types.name、hosts.name、products.name、products.keywords) 、products.description、products.uid)スコアとしてのAGAINST( '検索語')左側の製品をホストに追加左側のホストをhost.typeにホスト左側のホストタイプをhost.host_id = host_types.id左側にカテゴリをhost_types.category_id = categories.id WHERE MATCH(categories.name、host_types.name、hosts.name、products.name、products.キーワード、products.description、products.uid)AGAINST( '検索語')ORDER BYスコアDESC;
  • categories.name == FULLTEXT - 1

  • host_types.name ==フルテキスト - 2

  • hosts.name ==フルテキスト - 3

  • products.name、products.キーワード、products.description、products.uid == フルテキスト - 4

'' '' '

これが私のSQL構造です、そして私は上記のクエリを使いました。

SELECT categories.name ASカテゴリ、categories.id AS category_id、host_types.name AS host_type、host_types.id AS host_type_id、hosts.name ASホスト、hosts.id AS host_id、名前としてproducts.id、products.id AS product_id、productsキーワードとしてのキーワード、products.description AS説明、products.quantity AS数量、products.price AS価格、products.uid catalgueとしての一致MATCH(categories.name)CscoreとしてのAGAINST( '検索語')、MATCH(host_types.name) htscoreとしてのAGAINST( '検索語')、hscoreとしてのAGAINST( '検索語')、MATCH(products.name、products.キーワード、products.description、products.uid)AGAINST( '検索語' )スコアとして製品左側のJOINホストON products.host_id = hosts.id左側のJOINホストタイプON.host_id = host_types.id左側のカテゴリカテゴリhost_types.category_id = categories.id WHERE MATCH(categories.name)AGAINST( '検索用語')OR MATCH(host_types.name)AGAINST('検索用語m ')OR MATCH(hosts.name)AGAINST('検索語 ')OR MATCH(products.name、products.キーワード、products.description、products.uid)AGAINST('検索語 ')ORDER BY score DESC


CREATE TABLE `categories`(` id` int(5)符号なしNOT NULL auto_increment、 `display_order` int(5)符号なしデフォルトNULL、` name` varchar(64)デフォルトNULL、 `last_modified`タイムスタンプNOT NULLデフォルトCURRENT_TIMESTAMP更新時CURRENT_TIMESTAMP 、PRIMARY KEY( `id`)、UNIQUE KEY` order`( `display_order`)、FULLTEXT KEY` full_name`( `name`))ENGINE = MyISAM AUTO_INCREMENT = 6デフォルトCHARSET = latin1;

CREATE TABLE `host_types`(` id` int(5)符号なしNOT NULL auto_increment、 `category_id` int(5)符号なしデフォルトNULL、` display_order` int(5)符号なしデフォルトNULL、 `name` varchar(64)デフォルトNULL、更新時の `last_modified`タイムスタンプNOT NULLデフォルトCURRENT_TIMESTAMP、PRIMARY KEY(` id`)、UNIQUE KEY `order`(` category_id`、 `display_order`)、FULLTEXT KEY` full_name`( `name`)ENGINE = MyISAM AUTO_INCMENT = 13デフォルト文字= latin1;

CREATE TABLE `hosts`(` id` int(5)符号なしNOT NULL auto_increment、 `host_id` int(5)符号なしデフォルトNULL、` display_order` int(5)符号なしデフォルトNULL、 `name` varchar(64)デフォルトNULL、更新時の `last_modified`タイムスタンプNOT NULLデフォルトCURRENT_TIMESTAMP、PRIMARY KEY(` id`)、一意キー `order`(` host_id`、 `display_order`)、FULLTEXT KEY` full_name`( `name`) = 4デフォルト文字= latin1;

CREATE TABLE `products`(` id` int(11)符号なしNOT NULL auto_increment、 `host_id` int(5)符号なしデフォルトNULL、` display_order` int(5)符号なしデフォルトNULL、 `uid` varchar(10)デフォルトNULL、 `name` varchar(128)デフォルトNULL、` keywords`テキスト、 `description`テキスト、` price` decimal(10,2)デフォルトNULL、 `Quantity` int(11)符号なしデフォルトNULL、` last_modified`タイムスタンプNOT NULLデフォルトCURRENT_TIMESTAMP、更新時CURRENT_TIMESTAMP、PRIMARY KEY( `id`)、FULLTEXT KEY` full_name`( `name`、` keywords`、 `description`、` uid`)エンジン= MyISAM AUTO_INCREMENT = 14デフォルトCHARSET = latin1;

2 Answer


26


  • 全文インデックス(またはあらゆる種類のインデックス)を定義することはできません MySQLの複数のテーブル。 各索引定義は、正確に1つの表を参照します。 特定のフルテキストインデックス内のすべてのカラムは、同じテーブルからのものでなければなりません。

  • `MATCH()`関数の引数として指定された列は一部でなければなりません 単一のフルテキストインデックスの。 データベース内の全文索引の一部であるすべての列を検索するために `MATCH()`を1回呼び出すことはできません。

  • フルテキストインデックスは、 CHAR、` VARCHAR`、 および「TEXT」データ型。

  • 各テーブルにフルテキストインデックスを定義できます。

例:

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;


0


上記の答えを拡張するためだけに。 考慮すべき点がいくつかあります。 複数の行を結合したままGROUPを使用してそれらの行をグループ化する場合は、MAX()を取得する必要があります。 また、上記は、テーブルのうちの1つの関連性による順序付けのみを行うので、他のテーブルの関連性を無視する。

SELECT ... MAX(MATCH(categories.name)AGAINST( '検索語'))MAX(MATCH(ホスト名.name)AGAINST( '検索語'))MAX(MATCH(hosts.name)AGAINST( '検索語'))MAX(スコアとしてのMATCH(products.name、products.keywords、products.description、products.uid)AGAINST( '検索語'))製品からの場合左のホストをONの製品に追加するhost.id = hosts.id左のホストを選択host.typeのhosts.host_id =ホストの種類.id host_types.category_id = categories.id上のカテゴリを左に結合するどこでマッチ(categories.name)またはマッチ(host_types.name)に一致する(host_types.name)または一致(hosts.name)に一致する(hosts.name) '検索語')または一致(products.name、products.キーワード、products.description、products.uid)AGAINST( '検索語')ORDER BY score DESC;

これにより、すべてのテーブルから関連性を追加できます。 MAX()を使用すると、データをグループ化できます。 複数の行を左に結合しているときにも役立ちます。