0

我有一个名为列表的对象,列表可以有许多便利设施(将其与帖子、标签模型进行比较)。这是一种有/没有关系。所以我有一个amenities表格,它存储系统中可以有哪些便利设施,还有listings一个存储列表的表格,listing_amenities它存储便利设施。

问题是根据便利设施搜索列表

我可以根据列表的任何参数(租金、位置等)搜索列表,但不能根据便利设施搜索列表,因为这需要 2 表连接。我还没有真正想出一个有效的解决方案来做到这一点。因此,我想就如何在此基础上进行搜索提供一些帮助。

我能想到的一个解决方案是注入一个额外的字段,其中包含一组便利设施

 SELECT * 
 FROM(SELECT listings.*, GROUP_CONCAT(CONCAT("(",Concat(amenity_id,")"))) as amenities 
      FROM `listings`,`listing_amenities`  
      WHERE listings.id=listing_amenities.listing_id 
      GROUP BY listings.id) as rs  
 WHERE amenities like "%(1)%"

即连接并添加包含在 () 中的设施 ID 并搜索它们

这让我想到:便利设施仅用于列表上下文和搜索,所以为什么不以类似的格式(1)、(2)存储它们以在列表表的单独列中指示可用的便利设施并保存在表格中和额外的查询费用?这种方法有什么缺点(如果有的话)?

为了更容易理解表格

 Listing Table
 --------
 id title description rent

 Amenities
 -------------
 id name description

 Listing_Amenities
 ------------------
 id listing_id amenity_id

我想我可以删除第三张表

并修改列表

 Listing Table
 --------
 id title description rent amenties(the amenities available in the appartment wrapped in bracket)

喜欢

 1 "House in Downtown Discworld" "Nice house, running water, teleporter" 2000 "(1)(5)(7)"

这种让我无需加入即可按便利设施进行搜索。我可以在选择租金的地方运行相同的查询

并使用 where 子句搜索: where amenities like "%(1)%" AND amenities like "%(2)%"

我在这种方法中看到的唯一问题是删除异常,即如果我从系统中删除设施,它不会自动从列表中删除设施

但我认为这不太可能发生,因为设施是由管理员决定的,并且在网站启动之前几乎会被冻结,其次,虽然我们可能会添加新的设施,但我们不太可能删除任何设施。

有没有其他的缺点。你能强调一下具体的场景吗?我认为这比加入更有效。坦率地说,更容易把我的头包起来。我可能是错的

4

3 回答 3

4

无法从您的帖子中掌握表格模型......但总的来说,我认为您应该使用这样的多对多关系。一个单独的表,只是为了保存关系。

ListingsAmenities
----------
ListingID
AmenitiesID    

便利设施表应仅包含每个便利设施一次。然后你不必连接。

有了这个,您应该也可以根据设施 ID 搜索列表。

当您将关系存储在表格的一列中时,每个便利设施只能存储一个列表...或者您应该开始连接...相反,如果您像这样存储,同一个列表可以有许多行具有各种便利设施,这使得查询方便。

像这样。

ListingAmenitiesTable:

ListingID   AmenityID
---------   ----------
L1      A1
L1      A2
L2      A2
L2      A3      
于 2013-06-09T04:45:37.277 回答
1

传统的数据库设计推荐您描述的模型,将“多对多”关系提取到单独的表中。

这样做的原因有很多 - 不仅是“删除”异常,还有性能 - 解析 varchar 列以提取模式“(*)”比整数之间的连接要慢得多。想象一下,您需要查找所有具有“Ankh Morpork 市中心景观”和“步行距离到 Unseen 大学”的列表,但没有“直接访问 Fool's Guild”的查询。

于 2013-06-10T08:31:16.437 回答
1

在事务(而不是报告)系统中,预先优化性能通常是一个坏主意。 根据第三范式 (3NF) 构建您的模型,然后测试您的系统以查看它是否具有不可接受的性能。如果是这样,请仔细检查您的索引和查询计划,看看是否有优化性能的方法。作为最后的手段,非规范化您的数据。

您提出的 0NF 设计不太灵活且功能较弱,并且几乎肯定会比大规模的标准化设计 表现更差。假设连接效率低下是错误的。 RDBMS 是专门为擅长连接而构建的。

您可以使用 WHERE EXISTS 语法轻松地在查询中包含所需的便利设施。

SELECT L.*
FROM listings L
WHERE L.rent < 1000
  AND L.location = 'desirable-location-x'
  AND EXISTS (SELECT A.id 
              FROM amenities A
                inner join listing_amenities LA
                  on A.id = LA.amenities_id
              WHERE A.name like '%walk-in%'
                AND LA.listing_id = L.id)

请注意,使用 EXISTS 的相关子查询允许您在不违反任何正常形式的情况下找到您要查找的内容。如果您在交集表和listingsamenities表上有适当的索引,那么性能会很好。

于 2013-06-10T02:06:57.817 回答