Mysql - 帮我改变这个涉及多个连接和条件的搜索查询,以获得所需的结果

时间:2010-06-02 20:27:38

标签: mysql search tags join multiple-tables

关于系统:

  • 我们正在关注基于标签的搜索。

  • 教师创建包 - 存储在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');

导师Vivian Richards创建了两个Learning_packs - “Cricket 1”(活跃)和“Cricket 2”(不活跃)。

要求:

现在我想在搜索关键字上使用AND逻辑搜索learning_packs。帮助我修改以下查询,以便搜索这些术语的任意组合 - 包名或教师姓名,姓氏结果所有活动包(直接由那些导师创建的包或包)。

=============================================== =================================== 的 1。搜索“Vivian Richards”

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”会返回该包,但搜索Vivian Richards并不会返回相同的包。

1 个答案:

答案 0 :(得分:1)

第一个查询(搜索“Vivian Richards”)没有返回记录的原因是因为连接:

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

如果你看,ttagrelslearning_packs_tag_relations),id_tutor包含:

id_tutor   
52
52
52
52

tdtutor_details)包含:

id_tutor
60
61
62

因此,不能加入;这两列中没有任何值匹配。

一些观点/评论:

查看表格似乎有很多裁员。例如,如果教师,作者和用户完全相同,并且他们的详细信息在用户表中,那么引用教师,作者或用户的所有表都应链接到users.id_userlearning_packs_tag_relations表如果要将包链接到标记,则不需要id_tutor列。它只需要pack_idtag_id。这是因为learning_packs中的包已经通过users列链接到id_author表。

tutor_details表可能会消除我的理论,因为它似乎将导师与用户联系起来(区别我没有在其他地方推断),但id_tutor值似乎没有与任何事物联系在一起。

这里可能需要重新设计一些数据库;祝你好运。