基于一对多关系构建 SQL 查询
我有一个搜索页面,我试图在两个表上构建复杂的搜索条件,看起来像:
Users
ID NAME
1 Paul
2 Remy
...
Profiles
FK_USERS_ID TOPIC TOPIC ID
1 language 1
1 language 2
1 expertise 1
1 expertise 2
1 expertise 3
2 language 1
2 language 2
第二个表配置文件,列出了每个用户的“语言”或“专业知识”(以及其他内容),主题 id 是另一个表的外键,具体取决于主题(如果主题是“语言”,则主题 ID 是语言表中语言的 ID,等等...)。
搜索需要找到类似 的内容,其中用户名 LIKE %PAU%
且用户“拥有”语言 1 且拥有语言 2、拥有专业知识 1 且拥有专业知识 2。
任何帮助将不胜感激!我正在两个表上执行LEFT JOIN
,尽管我不确定这是正确的选择。我的主要问题在于“AND”。同一用户必须同时具备语言 1 和 2,并且同时具备专业知识 1 和 2。
我使用 PHP 工作,通常会尝试避免内部 SELECT 甚至联接,但我认为内部 SELECT 即将到来?
I have a search page where I am trying to build a complex search condition on two tables which look something like:
Users
ID NAME
1 Paul
2 Remy
...
Profiles
FK_USERS_ID TOPIC TOPIC ID
1 language 1
1 language 2
1 expertise 1
1 expertise 2
1 expertise 3
2 language 1
2 language 2
The second table Profiles, lists the "languages" or the "expertises" (among other stuff) of each user, and topic id is a foreign key to another table depending on the topic (if topic is "language", than topic ID is the ID of a language in the languages table, etc...).
The search needs to find something like where user name LIKE %PAU%
and the user "has" language 1 and has language 2 and has expertise 1 and has expertise 2.
Any help would be really appreciated! I am performing a LEFT JOIN
on the two tables although I am not sure that is the correct choice. My main problem lies on the "AND". The same user has to have both languages 1 and 2, and at the same time expertise 1 and 2.
I work in PHP and I usually try to avoid inner SELECTs and even joins, but I think an inner SELECT is imminent here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以通过构建一组与您的个人资料表中的条件相匹配的用户来实现此目的,如下所示:
在此处列出与您需要的主题相匹配的用户。通过按用户 ID 分组并指定应返回的行数,您可以有效地说“仅那些在主题 z 中具有 x 和 y 的行。只需确保 COUNT(1) = x 具有相同数量的不同行 解释
然后您可以查询用户表
您也可以在联接和派生表中执行此操作,但其本质应在上面进行
:
如果你正在寻找多种组合,你可以使用mysql的多列IN:
这将寻找与x-3、x-5、y-3和y-6对匹配的用途。
您应该能够在 php 中轻松构建 topic-topic_id 对并将其填充到 SQL 字符串中,并且只需将生成的对数计数到变量中以用于 count(1) 数字。请参阅http://www.mysqlperformanceblog .com/2008/04/04/multi-column-in-clause-unexpected-mysql-issue/ 使用此方法进行性能讨论。
You can accomplish this by building a set of users that matches the criterias from your profile tables, something like this:
Here you list your users that matches the topics you need. By grouping by the user id and specifying the amount of rows that should be returned, you can effectively say "only those that has x and y in topic z. Just make sure that the COUNT(1) = x has the same number of different TOPIC_IDs to look for.
You can then query the user table
You can also do it in a join and a derived table, but the essence should be explained above.
EDIT:
if you are looking for multiple combinations, you can use mysql's multi-column IN:
This will look for uses matching the pairs x-3, x-5, y-3 and y-6.
You should be able to build the topic-topic_id pairs easily in php and stuffing it into the SQL string, and also just counting the number of pairs you generate into a variable for using for the count(1) number. See http://www.mysqlperformanceblog.com/2008/04/04/multi-column-in-clause-unexpected-mysql-issue/ for performance talk using this approach.
不就是一个简单的经典INNER JOIN吗?
此查询将返回与模式匹配的用户的所有语言和专业知识及其 ID,在本例中,用户的名字中包含 Paul。这是你喜欢的吗?或者其他什么?
Isn't it just a simple classical INNER JOIN?
This query would return all the languages and expertise with their IDs for the users matching the pattern, in this case containing Paul in their name. Is this what you like? Or something else?
编辑:
好的,@cairnz 的答案略有不同:
EDIT:
Ok, a slight variation on @cairnz' answer:
我会根据您“需要”的每个条件多次执行 JOIN 条件。我还将确保基于要查找的键的每个部分在配置文件表上建立索引...(FK_User_ID、Topic_ID、主题)
这样,提供的其他答案中表达的任何其他标准都不会有太大影响。这些表是按标准设置的,就好像同时进行一样,如果有任何缺失,它们将立即从结果中排除,而不是尝试对每个条目进行子选择计数(我认为这可能是您遇到的滞后) 。
因此,您的每个“必需”条件都将采用相同的“JOIN”构造,正如您所看到的,我只是增加连接实例的“别名”。
I would do based on JOIN conditions multiple times against each condition that you are "requiring". I would also ensure an index on the Profiles table based on the each part of the key looking for... (FK_User_ID, Topic_ID, Topic)
This way, any additional criteria as expressed in other answer provided shouldn't be too much an impact. The tables are setup by the criteria as if simultaneous, and if any are missing, they will be excluded from the result immediately instead of trying to do a sub-select counting for every entry (which I think might be the lag you are encountering).
So, each of your "required" criteria would take the same "JOIN" construct, and as you can see, I'm just incrementing the "alias" of the join instance.