I have a few Models in my code which is modeled in my MySQL database in this structure:
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 |
+----+--------------+-----------+--------------+
As you can see from the table structure all models can be linked back to a property
record (either directly or via one or more intermediary tables).
In my code I want to write one query that will get the property.id
of a file
After looking over this question: Joining different tables based on column value I realized finding a "link" from a file
to a property
can be done via a few joins.
The number of joins needed is different based on whatever the parent_model
is. For file.id
= 1 its a matter of joining in the properties
table. For file.id
= 3 we must join in costs
, tenants
, and properties
How should a query be written that can get a property.id
for all of my files
records?
Edit: This would be a sample output:
+---------+-------------+
| file_id | property_id |
|---------+-------------|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
+---------+-------------+
In this case all the files worked out to be associated with property_id
1 but this may not always be the case.
I don't think there's a shortcut. You need to traverse all the paths something along these lines
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.
ie just string together all the variations then UNION
You should be able to do this like so:
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)
Depending on your data, this might break down. I don't think that I like the table design in this case.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.