一对多表中的sql选择
我有 3 个表,其中包含以下列:
Topics: [TopicID] [TopicName]
Messages: [MessageID] [MessageText]
MessageTopicRelations [EntryID] [MessageID] [TopicID]
消息可以涉及多个主题。问题是:给定几个主题,我需要获取关于所有这些主题的消息,而且不少于,但它们也可以是关于其他一些主题的。与其中一些给定主题相关的消息将不包括在内。我希望我很好地解释了我的要求。否则我可以提供样本数据。谢谢
I have got 3 tables with those columns below:
Topics: [TopicID] [TopicName]
Messages: [MessageID] [MessageText]
MessageTopicRelations [EntryID] [MessageID] [TopicID]
messages can be about more than one topic. question is: given couple of topics, I need to get messages which are about ALL these topics and not the less, but they can be about some other topic too. a message which is about SOME of these given topics won't be included. I hope I explained my request well. otherwise I can provide sample data. thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
以下使用
x
、y
和z
代表主题 ID,但未提供任何示例。使用 JOIN:
使用 GROUP BY/HAVING COUNT(*):
在这两种方法中,JOIN 方法更安全。
GROUP BY/HAVING 依赖于
MESSAGETOPICRELATIONS.TOPICID
作为主键的一部分,或者具有唯一键约束以确保不存在重复项。否则,您可能有 2 个以上的同一主题实例与一条消息关联 - 这将是误报。使用HAVING COUNT(DISTINCT ...
会清除任何误报,但支持取决于数据库 - MySQL 在 5.1+ 上支持它,但在 4.1 上不支持。Oracle 可能必须等到周一才能看到在 SQL Server 上进行测试...我查看了 Bill 的关于不需要加入
TOPICS
表的评论:...将返回误报 - 与
TOPICS
表中定义的至少一个值匹配的行code>IN 子句。并且:...根本不会返回任何内容,因为
topicid
永远不可能同时包含所有值。The following use
x
,y
, andz
to stand in for topic ids, being that none were provided for examples.Using JOINs:
Using GROUP BY/HAVING COUNT(*):
Of the two, the JOIN approach is safer.
The GROUP BY/HAVING relies on the
MESSAGETOPICRELATIONS.TOPICID
being either part of the primary key, or having a unique key constraint to ensure there aren't duplicates. Otherwise, you could have 2+ instances of the same topic associated to a message - which would be a false positive. UsingHAVING COUNT(DISTINCT ...
would clear up any false positives, but support depends on the database - MySQL supports it at 5.1+, but not on 4.1. Oracle might, have to wait till Monday to test on SQL Server...I looked into Bill's comment about not needing the join to the
TOPICS
table:...will return false positives - rows that match at least one of the values defined in the
IN
clause. And:...won't return anything at all, because the
topicid
can never be all of the values at once.这是一个非常不优雅的解决方案
Here's a profoundly inelegant solution
编辑:感谢@Paul Creasey 和@OMG Ponies 发现我方法中的缺陷。
正确的方法是对每个主题进行自连接;如主要答案所示。
另一个极其不雅的条目:
Edit: thanks to @Paul Creasey and @OMG Ponies for finding the flaws in my approach.
The correct way to do this is with a self-join for each topic; as shown in the leading answer.
Another profoundly inelegant entry:
回复:OMG Ponies 的回答,您不需要加入
TOPICS
表。HAVING COUNT(DISTINCT)
子句在 MySQL 5.1 中运行良好。我刚刚测试过。这就是我的意思:
使用 GROUP BY/HAVING COUNT(*):
我建议
COUNT(DISTINCT)
的原因是,如果列(messageid,topicid)
不存在如果没有唯一约束,则可能会出现重复项,这会导致组中的计数为 3,即使不同值少于三个也是如此。Re: the answer by OMG Ponies, you don't need to join to the
TOPICS
table. And theHAVING COUNT(DISTINCT)
clause works fine in MySQL 5.1. I just tested it.This is what I mean:
Using GROUP BY/HAVING COUNT(*):
The reason that I suggest
COUNT(DISTINCT)
is that if the columns(messageid,topicid)
don't have a unique constraint, you could get duplicates, which would result in a count of 3 in the group, even with fewer than three distinct values.