如何在我的mysql数据库中执行此搜索的最佳方法?

时间:2019-02-13 21:16:59

标签: mysql sql

我有3个表及其各自的结构:

users: id(1),name
colors: id(2),name,tags
hobbies: id(3),name,tags
userSettings: id,int(1) userid,int(2) color,int(3) hobbie

表格值:

users: {1,john},{2,ana}

colors: {1,blue,blue azul celeste },{2,red,red vermelho rosso}

hobbies: {1,sing,cantare cantar sing},{2,run,running correr runner}

userSettings: {1,1,1,2},{2,2,2,1}

所以...我需要的是找到具有用户搜索过的颜色或嗜好的用户。例如:如果我按"blue""runner"搜索,则必须找到用户1 - John

如果按"rosso""sing"搜索,则必须找到用户2 - Ana。我知道如何使用3个查询来执行此操作,但我知道存在一种方法可以将其改进为仅一个查询,因为对字段进行了索引会很快。

有人可以帮忙吗?

4 个答案:

答案 0 :(得分:0)

这实际上取决于您如何实现搜索(我假设您使用的是PHP?)

通常,如果您将单词替换为搜索表单中的变量,则可以执行以下操作:

模式(MySQL v5.7)

create table users (id int, name varchar(10));
create table colors (id int, name varchar(10), tags varchar(50));
create table hobbies (id int, name varchar(10), tags varchar(50));
create table userSettings (id int, user_id int, color_id int, hobbie_id int);

insert into users values (1, 'John');
insert into users values (2, 'Ana');

insert into colors values (1,'blue','blue azul celeste');
insert into colors values (2,'red','red vermelho rosso');

insert into hobbies values (1,'sing','cantare cantar sing');
insert into hobbies values (2,'run','running correr runner');

insert into userSettings values (1,1,1,2);
insert into userSettings values (2,2,2,1);                                                             

查询#1

select u.* from users u, colors c, hobbies h, userSettings us 
where 
us.user_id = u.id and
us.color_id = c.id and
us.hobbie_id = h.id and
(c.tags like '%blue%' or 
 h.tags like '%blue%' or 
c.name like '%blue%' or 
 h.name like '%blue%'
);

| id  | name |
| --- | ---- |
| 1   | John |

View on DB Fiddle

答案 1 :(得分:0)

以下查询应按预期完成任务。逻辑是使用LEFT JOIN作为桥,将userscolors表与hobbies表一起使用。在连接条件中检查搜索参数。然后,userSettings子句确保至少一个爱好或颜色与搜索参数匹配:

WHERE

您可以在此 demo on DB Fiddle 中看到对您的示例数据的操作。例如,当搜索SELECT u.* FROM users u LEFT JOIN userSettings us ON us.user_id = u.id LEFT JOIN colors c ON c.id = us.color_id AND ( c.name = @search OR c.tags LIKE CONCAT('%', @search, '%') ) LEFT JOIN hobbies h ON h.id = us.hobbie_id AND (h.name = @search OR h.tags LIKE CONCAT('%', @search, '%') ) WHERE c.id IS NOT NULL OR h.id IS NOT NULL 时,将返回:

'sing'

答案 2 :(得分:0)

向要搜索的表中添加全文索引,然后在查询中联接这些表。

https://www.db-fiddle.com/f/peZLQ6PVLMRCytcP9EUp3f/12

架构

CREATE TABLE users (
id int NOT NULL AUTO_INCREMENT,
name varchar(255),
PRIMARY KEY (id)
);
INSERT INTO users (name) VALUES ('john'), ('ana');

CREATE TABLE colors (
id int NOT NULL AUTO_INCREMENT,
name varchar(255),
tags varchar(255),
PRIMARY KEY (id),
FULLTEXT (tags)
);
INSERT INTO colors (name, tags)
VALUES
('blue','blue azul celeste'), 
('red','red vermelho rosso');

CREATE TABLE hobbies (
id int NOT NULL AUTO_INCREMENT,
name varchar(255),
tags varchar(255),
PRIMARY KEY (id),
FULLTEXT (tags)
);
INSERT INTO hobbies (name, tags)
VALUES
('sing','cantare cantar sing'), 
('run','running correr runner');

CREATE TABLE userSettings (
id int NOT NULL AUTO_INCREMENT,
userid int,
color int,
hobbie int,
PRIMARY KEY (id)
);
INSERT INTO userSettings (userid, color, hobbie)
VALUES
(1,1,2), 
(2,2,1);

查询

SELECT users.* FROM users 
LEFT JOIN userSettings ON userSettings.userid = users.id 
LEFT JOIN colors ON colors.id = userSettings.color 
LEFT JOIN hobbies ON hobbies.id = userSettings.hobbie 
WHERE 
MATCH(colors.tags) AGAINST ('runner' IN BOOLEAN MODE)
OR MATCH(hobbies.tags) AGAINST ('runner' IN BOOLEAN MODE)
;


或者,您可以创建一个view表。 EG:
https://www.db-fiddle.com/f/8kojtBefpySA4ckDqM747H/2

架构

//As above +

CREATE VIEW searchview AS (SELECT userid, users.name as name, concat_ws(' ',colors.tags,hobbies.tags) as tags FROM users 
LEFT JOIN userSettings ON userSettings.userid = users.id 
LEFT JOIN colors ON colors.id = userSettings.color 
LEFT JOIN hobbies ON hobbies.id = userSettings.hobbie);

查询

SELECT * FROM searchview
WHERE tags REGEXP '[[:<:]]runner[[:>:]]';

答案 3 :(得分:0)

尝试一下:

SELECT DISTINCT u.id || ' - ' || u.name as USER
FROM userSettings us
JOIN users u
    ON u.id = us.userid
JOIN colors c
    ON c.id = us.color
JOIN hobbies h
    ON h.id = us.hobbie
WHERE 
    c.name LIKE '%blue%'
    OR c.tags LIKE '%blue%'
    OR h.name LIKE '%runner%'
    OR h.tags LIKE '%runner%';

输入: 搜索蓝色或亚军

输出:

USER
1 - John