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

О системе:

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

  • Репетиторы создают пакеты - отношения тегов для наставников, хранящиеся в 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_pack - «Крикет 1» (активный) и «Крикет 2» (неактивный).

Требование:

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

================================================== ================================ 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. Поиск "Cricket 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

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


person Sandeepan Nath    schedule 02.06.2010    source источник


Ответы (1)


Причина, по которой первый запрос (поиск "Вивиан Ричардс") не возвращает записей, связана с объединением:

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, похоже, ни с чем не связаны.

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

person JYelton    schedule 02.06.2010
comment
Я упростил структуру таблиц и задал вопрос на более простом примере. Пожалуйста, посмотри, сможешь ли ты помочь. stackoverflow.com/questions/3030022/ - person Sandeepan Nath; 13.06.2010
comment
Я еще раз посмотрю, когда у меня будет время - person JYelton; 14.06.2010