根据列值连接可变数量的表

时间:2016-03-24 01:42:32

标签: mysql sql join

我的代码中有一些模型,在我的MySQL数据库中以这种结构建模:

 Properties
+----+------+---------+
| id | name | address |
|----+------+---------|
| 1  | p1   | 123 st  |
| 2  | p2   | 123 st  |
| 2  | p3   | 123 st  |
+----+------+---------+

 Tenants (belongs to property)
+----+-------------+-------+
| id | property_id | suite |
|----+-------------+-------|
| 1  | 1           | s1    |
| 2  | 1           | s2    |
| 3  | 2           | s3    |
+----+-------------+-------+

 Costs (can belong to property or tenants)
+----+--------------+-----------+--------------+
| id | parent_model | parent_id | name         |
|----+--------------+-----------+--------------+
| 1  | property     | 1         | gardening    |
| 2  | property     | 2         | construction |
| 3  | tenant       | 1         | renovation   |
+----+--------------+-----------+--------------+

 Files (can belong to any model)
+----+--------------+-----------+--------------+
| id | parent_model | parent_id | name         |
|----+--------------+-----------+--------------+
| 1  | property     | 1         | file1.jpg    |
| 2  | tenant       | 2         | file2.pdf    |
| 3  | costs        | 3         | file3.doc    |
+----+--------------+-----------+--------------+

从表结构中可以看出,所有模型都可以链接回property记录(直接或通过一个或多个中间表)。

在我的代码中,我想编写一个查询来获取property.id的{​​{1}} 在查看了这个问题之后:Joining different tables based on column value我意识到可以通过几个连接找到从filefile的“链接”。

根据property的不同,所需的连接数不同。对于parent_model = 1,它是加入file.id表的问题。对于properties = 3,我们必须加入file.idcoststenants

如何编写可以获得properties所有property.id条记录的files的查询?

编辑: 这将是一个示例输出:

+---------+-------------+
| file_id | property_id |
|---------+-------------|
| 1       | 1           |
| 2       | 1           |
| 3       | 1           |
+---------+-------------+

在这种情况下,所有文件都与property_id 1相关联,但情况可能并非总是如此。

2 个答案:

答案 0 :(得分:2)

我认为没有捷径。你需要沿着这些线遍历所有路径

select -- property files
FileID, parent_id 
from Files 
where parent_model='property'
union
select -- property costs
FileID, c.parent_id
from
Files inner join costs C on Files.parent_id=c.id and c.parent_model='property'
where Files.parent_model='costs'
union
select -- tenant costs
FileID, t.parent_id
Files inner join costs C on Files.parent_id=c.id and c.parent_model='tenant'
inner join tenant t on t.id=c.parent_id  
where Files.parent_model='costs'
.... etc.

即。然后将所有变体串联起来UNION

答案 1 :(得分:1)

您应该能够这样做:

SELECT
    P.id,
    P.name,
    P.address,
    F.name,
    ...
FROM
    Files F
LEFT OUTER JOIN Costs C ON
    F.parent_model = 'Cost' AND C.id = F.parent_id
LEFT OUTER JOIN Tenants T ON
    (F.parent_model = 'Tenant' AND T.id = F.parent_id) OR
    (C.parent_model = 'Tenant' AND T.id = C.parent_id)
LEFT OUTER JOIN Properties P ON
    (F.parent_model = 'Property' AND P.id = F.parent_id) OR
    (C.parent_model = 'Property' AND P.id = C.parent_id) OR
    (P.id = T.property_id)

根据您的数据,这可能会中断。在这种情况下,我不认为我喜欢桌子设计。