如何在INNER JOIN查询中避免笛卡尔积?

时间:2010-05-20 09:00:56

标签: sql inner-join cartesian-product

我有6张桌子,我们称之为a,b,c,d,e,f。现在我想搜索某个单词的所有表的所有列(ID列除外),让我们说'Joe'。我做的是,我在所有表上进行了INNER JOINS,然后使用LIKE搜索列。

INNER JOIN
...
ON
INNER JOIN
...
ON.......etc.
WHERE a.firstname 
~* 'Joe' 
OR a.lastname 
~* 'Joe' 
OR b.favorite_food 
~* 'Joe'
OR c.job
~* 'Joe'.......etc.

结果是正确的,我得到了我正在寻找的所有colums。但是我也得到了某种笛卡尔积,我得到2行或更多行几乎相同的结果。

我该如何避免这种情况?我想要每行只有一次,因为结果应该出现在网络搜索中。

更新

我首先尝试通过使用此声明来确定SELECT DISTINCT是否有效:pastie.org/970959但它仍然给我一个笛卡尔积。这有什么问题?

5 个答案:

答案 0 :(得分:2)

试试SELECT DISTINCT

答案 1 :(得分:2)

你在JOIN这个tables的条件是什么?你有foreign keys还是什么?

也许你应该分别在每张桌子上找到这个词?

答案 2 :(得分:1)

您使用的是哪种服务器? Microsoft SQL Server具有全文索引功能(我认为其他人也有这样的功能),它允许您以更少资源密集的方式搜索关键字。

另外考虑使用UNION而不是连接表。

答案 3 :(得分:0)

没有看到你的牌桌,我只能真正假设这里发生的事情是你在某处有一对多的关系。您可能希望在子查询中执行所有操作,选择不同的ID,然后获取要通过ID显示的数据。类似的东西:

SELECT a.*, b.*
FROM (SELECT DISTINCT a.ID
      FROM ...
      INNER JOIN ...
      INNER JOIN ...
      WHERE ...) x
INNER JOIN a ON x.ID = a.ID
INNER JOIN b ON x.ID = b.ID

但有几点需要注意:

  • 这将是 sloooow ,您可能希望使用全文搜索(如果您的RDBMS支持)。

  • 单独搜索每个表可能会更快,而不是首先加入笛卡尔积中的所有内容,然后使用OR进行过滤。

答案 4 :(得分:0)

如果您的表是实体类型表,例如a是个人而b是公司,我认为如果您搜索,则不能避免使用笛卡尔积以这种方式得到结果(单一查询)。

您说要在所有表中搜索某个单词,但您可能希望将结果分成相应的类型。对?否则,网络搜索没有多大意义。 因此,如果您搜索“Joe”,您希望看到名为“Joe”的人,例如名为“Joe's gym”的公司。由于您要搜索不同的实体,因此应将搜索拆分为不同的查询。

如果您确实想在一个查询中执行此操作,则必须更改数据库结构以适应。您将需要某种形式的“搜索表”,其中包含实体ID(PK)和实体类型,以及您希望找到该实体的关键字列表。例如:

EntityType, EntityID, Keywords
------------------------------
Person,     4,        'Joe', 'Doe'
Company,    12,       'Joe''s Gym', 'Gym'

那样的东西?

然而当您的搜索只返回一种类型的实体(比如一个Person)时,它会有所不同,并且您希望返回对该关键字有效的人(在任何相关的表中)人)。然后,您需要选择要显示的所有字段并按其分组,而不显示您要搜索的字段。包括它们不可避免地导致笛卡尔积。

顺便说一句,我只是在这里集思广益。希望它有所帮助。