0

我有一个我似乎无法找到解决方案的问题。我在这里浏览了类似的答案,但没有什么是我想要的。我对 SQL 相当熟悉,但无论如何都不是专家。

我有一张关于公寓楼信息的表格 - 名称、区域、社区、电话号码、地址、邮编等。目前,我在这张表格中定义了几个便利设施,例如“门卫”、“电梯”、“健身房”(和其他几个)作为tinyints来指示建筑物是否确实具有这种舒适性。然而,我正在整合更多的便利设施类型,我认为这可能是改变结构的时候了,因为在巨大的建筑物桌子上添加柱子并没有太大意义。

因此,我正在寻找一种解决方案,它可以为我提供执行以下操作的最佳能力:1) 根据用户定义的便利设施搜索建筑物(例如,用户选择他想查看必须有健身房和门卫的建筑物,不关心其他人)2)返回有关建筑物的数据,包括建筑物包含的所有便利设施(用于显示信息)

我正在考虑将这些结构分成多对多关系并执行以下操作:1)创建名为“设施”的新表,其中包含所有设施,具有以下结构:id -> 设施名称的唯一 id -> amenity 值的文本描述 -> 例如“pet_friendly”(用于在表单中搜索,不确定是否有必要)

2) 在另一个名为“building_amenities”的表中创建建筑物和便利设施之间的关系表,其结构如下: id -> 关系 building_id 的唯一 id -> 引用建筑物 amenity_id 的 id -> 引用 amenity 的 id value -> tinyint,建筑物是否有便利设施 在这张表中,每栋建筑都会与每个便利设施有关系,并指示它是否有。

我的问题是我不确定这是否是适合这种情况的正确结构,如果我有这种结构,我当然不知道如何实现搜索查询。

非常感谢您对此的任何帮助!

4

3 回答 3

1

我建议您创建一个建筑物表、一个设施表和一个关系表。每个建筑物都有一个 ID,每个设施也有一个 ID。要选择所有具有某些设施的建筑物,您只需编写如下查询

SELECT *
FROM (relational_table) rt JOIN (buildings_table) bt
    ON rt.id_building = bt.id_building JOIN (amenities_table) at
    ON at.id_amenity = rt.id_amenity
WHERE rt.id_amenity = ... (OR, AND etc.)

要返回带有便利设施的建筑物,您只需将 WHERE 子句更改为 WHERE id_building = x,然后应选择所有便利设施。

于 2012-04-13T21:57:25.840 回答
0

除了 building_amenities 表中的 tinyint 标志之外,我将拥有一切。如果便利设施在现实生活中确实存在,我只会在该表中记录。

这样,您可以编写查询以使用常规连接查找具有给定设施的所有建筑物:

select * from buildings
    join building_amenities on buildings.id=building_amenities.building_id
    join amenities on building_amenities.amenity_id=amenities.id
where amenities.name='doorman'

如果你想得到没有(比如)门卫的建筑物,你可以使用左连接:

select * from amenities
    left join building_amenities on amenities.id=building_amenities.amenity_id
    left join buildings on building_amenities.buildings_id=buildings.id
where buildings.id is NULL and amenities.name='doorman'
于 2012-04-13T21:58:40.013 回答
0

正如菲尔凯恩斯已经建议的那样,您不应该在关联表中包含 TINYINT (伪布尔值)。如果建筑物存在设施,则关联表中应该只有一条记录。

使用多个连接执行良好,但您可以使用 GROUP BY ... HAVING COUNT 获得相同(甚至稍微更好)的性能,并且更容易操作多个条件的查询。

因此,如果您想找到所有具有设施 1、2 和 4 的建筑物,您可以这样做 -

SELECT b.*
FROM buildings b
INNER JOIN building_amenities ba
    ON b.id = ba.building_id
WHERE ba.amenity_id IN (1,2,4)
GROUP BY b.id
HAVING COUNT(ab.amenity_id) = 3

如果您想查找所有具有便利设施 1、2、4、7、13、19 和 23 的建筑物,则查询变为 -

SELECT b.*
FROM buildings b
INNER JOIN building_amenities ba
    ON b.id = ba.building_id
WHERE ba.amenity_id IN (1,2,4,7,13,19,23)
GROUP BY b.id
HAVING COUNT(ab.amenity_id) = 7

如果您需要显示建筑物的所有设施,您可以在设施表中添加第二个连接 -

SELECT b.*, GROUP_CONCAT(DISTINCT ab2.amenity_id)
FROM buildings b
INNER JOIN building_amenities ba
    ON b.id = ba.building_id
INNER JOIN building_amenities ba2
    ON b.id = ba2.building_id
WHERE ba.amenity_id IN (1,2,4,7,13,19,23)
GROUP BY b.id
HAVING COUNT(DISTINCT ab.amenity_id) = 7
于 2012-04-14T01:25:31.713 回答