具有设施的建筑物的SQL结构

时间:2012-04-13 21:46:46

标签: mysql database database-design relational-database

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

我有一张表格,里面有关于公寓楼的信息 - 姓名,地区,社区,电话号码,地址,邮编等。目前,我在这张桌子内有几个设施,如“门卫”,“电梯”,“健身房“(以及其他一些人)作为小物件来表明建筑物是否确实具有这种舒适性。但是,我正在整合更多的舒适性类型,我认为这可能是改变结构的时候,因为在一个巨大的建筑物表中添加一个列并没有多大意义。

所以我正在寻找能够为我提供最佳能力的解决方案: 1)根据用户定义的设施搜索建筑物(例如,用户选择他想要看到必须有健身房和门卫的建筑物,而不关心其他建筑物) 2)返回有关建筑物的数据,包括建筑物包含的所有设施(用于显示信息)

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

2)在另一个名为“building_amenities”的表中创建建筑物和设施之间的关系表,其结构如下:     id - >这段关系的独特身份     building_id - >是指建筑物的id     amenity_id - >指的是一个舒适的id     价值 - > tinyint,无论建筑物是否具有舒适性 在这张表中,每个建筑物都与每个建筑物有关系并指示它是否具有它。

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

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

3 个答案:

答案 0 :(得分:1)

我建议您创建建筑物表,设施表和关系表。每栋建筑都有一个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,然后选择所有设施。

答案 1 :(得分: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'

答案 2 :(得分:0)

正如Phil Cairns已经建议的那样,你不应该在关联表中使用TINYINT(伪布尔值)。如果建筑物存在舒适性,则关联表中应该只有一条记录。

使用多个连接可以很好地执行,但是您可以使用GROUP BY获得相同的(or even slightly better)性能... HAVING COUNT并且更容易操作查询以满足多个条件。

所以如果你想找到所有有1,2号和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和1的建筑物。 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