Mysql - Помогите мне изменить этот поисковый запрос, включающий несколько соединений и условий, чтобы получить желаемые результаты - PullRequest
0 голосов
/ 03 июня 2010

О системе:

  • Мы следим за поиском на основе тегов.

  • Преподаватели создают пакеты - отношения тегов для преподавателей, хранящихся в tutors_tag_relations, и для пакетов, хранящихся в learning_packs_tag_relations. Все теги хранятся в таблице тегов.

  • В системе имеется 6 таблиц - репетиторы, пользователи (связаны с tutor_details), learning_packs, learning_packs_tag_relations, tutors_tag_relations и теги.

Пожалуйста, запустите следующие свежие запросы для настройки системы:

CREATE TABLE IF NOT EXISTS learning_packs_tag_relations ( id_tag int(10) unsigned NOT NULL DEFAULT '0', id_tutor int(10) DEFAULT NULL, id_lp int(10) unsigned DEFAULT NULL, KEY Learning_Packs_Tag_Relations_FKIndex1 (id_tag), KEY id_lp (id_lp), KEY id_tag (id_tag) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS learning_packs ( id_lp int(10) unsigned NOT NULL AUTO_INCREMENT, id_status int(10) unsigned NOT NULL DEFAULT '2', id_author int(10) unsigned NOT NULL DEFAULT '0', name varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (id_lp) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=21 ;

CREATE TABLE IF NOT EXISTS tutors_tag_relations ( id_tag int(10) unsigned NOT NULL DEFAULT '0', id_tutor int(10) DEFAULT NULL,

KEY Tutors_Tag_Relations (id_tag), KEY id_tutor (id_tutor), KEY id_tag (id_tag) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS users ( id_user int(10) unsigned NOT NULL AUTO_INCREMENT, name varchar(100) NOT NULL DEFAULT '', surname varchar(155) NOT NULL DEFAULT '',

PRIMARY KEY (id_user)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=52 ;

CREATE TABLE IF NOT EXISTS tutor_details ( id_tutor int(10) NOT NULL AUTO_INCREMENT, id_user int(10) NOT NULL, PRIMARY KEY (id_tutor) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=60 ;

CREATE TABLE IF NOT EXISTS tags ( id_tag int(10) unsigned NOT NULL AUTO_INCREMENT, tag varchar(255) DEFAULT NULL, PRIMARY KEY (id_tag), UNIQUE KEY tag (tag) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

ALTER TABLE learning_packs_tag_relations ADD CONSTRAINT Learning_Packs_Tag_Relations_ibfk_1 FOREIGN KEY (id_tag) REFERENCES tags (id_tag) ON DELETE NO ACTION ON UPDATE NO ACTION;

ALTER TABLE learning_packs

ADD CONSTRAINT Learning_Packs_ibfk_2 FOREIGN KEY (id_author) REFERENCES users (id_user) ON DELETE NO ACTION ON UPDATE NO ACTION;

ALTER TABLE tutors_tag_relations ADD CONSTRAINT Tutors_Tag_Relations_ibfk_1 FOREIGN KEY (id_tag) REFERENCES tags (id_tag) ON DELETE NO ACTION ON UPDATE NO ACTION;

INSERT INTO test.users ( id_user , name , surname ) VALUES ( NULL , 'Vivian', 'Richards' ), ( NULL , 'Sachin', 'Tendulkar' );

INSERT INTO test.users ( id_user , name , surname ) VALUES ( NULL , 'Don', 'Bradman' );

INSERT INTO test.tutor_details ( id_tutor , id_user ) VALUES ( NULL , '52' ), ( NULL , '53' );

INSERT INTO test.tutor_details ( id_tutor , id_user ) VALUES ( NULL , '54' );

INSERT INTO test.tags ( id_tag , tag ) VALUES ( 1 , 'Vivian' ), ( 2 , 'Richards' );

INSERT INTO test.tags (id_tag, tag) VALUES (3, 'Sachin'), (4, 'Tendulkar'); INSERT INTO test.tags (id_tag, tag) VALUES (5, 'Don'), (6, 'Bradman');

INSERT INTO test.learning_packs (id_lp, id_status, id_author, name) VALUES ('1', '1', '52', 'Cricket 1'), ('2', '2', '52', 'Cricket 2');

INSERT INTO test.tags (id_tag, tag) VALUES ('7', 'Cricket'), ('8', '1'); INSERT INTO test.tags (id_tag, tag) VALUES ('9', '2');

INSERT INTO test.learning_packs_tag_relations (id_tag, id_tutor, id_lp) VALUES ('7', '52', '1'), ('8', '52', '1'); INSERT INTO test.learning_packs_tag_relations (id_tag, id_tutor, id_lp) VALUES ('7', '52', '2'), ('9', '52', '2');

Репетитор Вивиан Ричардс создал два пакета Learning_packs - «Крикет 1» (активный) и «Крикет 2» (неактивный).

Требования:

Теперь я хочу выполнить поиск learning_packs, используя логику AND для поиска по ключевым словам. Помогите мне изменить следующий запрос, чтобы при поиске по любой комбинации этих терминов - имени пакета или имени преподавателя, фамилии были получены все активные пакеты (либо непосредственно эти пакеты, либо пакеты, созданные этими преподавателями).

=============================================== =================================== 1. Поиск "Вивиан Ричардс"

select lp.*

from Learning_Packs AS lp

LEFT JOIN Learning_Packs_Tag_Relations AS lptagrels ON lp.id_lp = lptagrels.id_lp

LEFT JOIN Tutors_Tag_Relations as ttagrels ON lp.id_author = ttagrels.id_tutor LEFT JOIN Tutor_Details AS td ON ttagrels.id_tutor = td.id_tutor LEFT JOIN Users as u on td.id_user = u.id_user

JOIN Tags as t on (t.id_tag = lptagrels.id_tag) or (t.id_tag = ttagrels.id_tag)

where lp.id_status = 1 AND ( t.tag LIKE "%Vivian%" OR t.tag LIKE "%Richards%" )
group by lp.id_lp HAVING count(lp.id_lp) > 1 limit 0,20

2. Поиск "Крикет 1"

select lp.*

from Learning_Packs AS lp

LEFT JOIN Learning_Packs_Tag_Relations AS lptagrels ON lp.id_lp = lptagrels.id_lp

LEFT JOIN Tutors_Tag_Relations as ttagrels ON lp.id_author = ttagrels.id_tutor LEFT JOIN Tutor_Details AS td ON ttagrels.id_tutor = td.id_tutor LEFT JOIN Users as u on td.id_user = u.id_user

JOIN Tags as t on (t.id_tag = lptagrels.id_tag) or (t.id_tag = ttagrels.id_tag)

where lp.id_status = 1 AND ( t.tag LIKE "%Cricket%" OR t.tag LIKE "%1%" ) group by lp.id_lp HAVING count(lp.id_lp) > 1 limit 0,20

Как видите, поиск "Крикет 1" возвращает этот пакет, но поиск Вивиан Ричардс не возвращает тот же пакет.

1 Ответ

1 голос
/ 03 июня 2010

Причина, по которой первый запрос (Поиск «Vivian Richards») не возвращает записей, связана с объединением:

LEFT JOIN Tutor_Details AS td ON ttagrels.id_tutor = td.id_tutor

Если вы посмотрите, ttagrels (то есть learning_packs_tag_relations), id_tutor содержит:

id_tutor   
52
52
52
52

Принимая во внимание, что td (то есть tutor_details) содержит:

id_tutor
60
61
62

Из-за этого не может быть никакого соединения; ни одно из значений в этих двух столбцах не совпадает.

Некоторое мнение / комментарий:

Просматривая таблицы, кажется, что есть много избыточностей. Например, если репетитор, автор и пользователь - это одно и то же, а их данные находятся в таблице пользователей, то все таблицы, которые относятся к репетитору, автору или пользователю, должны ссылаться на users.id_user. Таблица learning_packs_tag_relations не нуждается в столбце id_tutor, если она связывает пакеты с тегами. Ему просто нужно pack_id и tag_id. Это связано с тем, что пакет, который находится в learning_packs, уже связан с таблицей users через столбец id_author.

Таблица tutor_details - это та, которая может развеять мою теорию, потому что она, кажется, связывает преподавателей с пользователями (с разграничением, которое я не экстраполировал в других местах), однако значения id_tutor, похоже, не связаны ни с чем .

Возможно, здесь требуется некоторая редизайн базы данных; удачи.

...