0

To summarize, I have several companies that own multiple sites and multiple divisions. Each division has one or more sites. I am reusing the division and site tables for all companies. I essentially have a global pool of divisions and sites for each company to pull from. My end goal is to pull all of the sites belonging to a division of a company.

Company 1  
   |  
   + Division 1  
   |      |  
   |      + Site 1  
   |      + Site 2  
   |
   + Division 2  
   |  
Company 2
   |
   + Division 3  
   |      |  
   |      + Site 3  
   |      + Site 2 
   | 
   + Division 1  
   |

company

+----+-------------+  
| id |    name     |  
+----+-------------+ 
| 1  |  company 1  |
+----+-------------+
| 2  |  company 2  |
+----+-------------+ 

sites

+----+-------------+  
| id |    name     |  
+----+-------------+ 
| 1  |   site 1    |
+----+-------------+
| 2  |   site 2    |
+----+-------------+
| 3  |   site 3    |
+----+-------------+

divisions

+----+-----------------+  
| id |      name       |  
+----+-----------------+ 
| 1  |   division 1    |
+----+-----------------+
| 2  |   division 2    |
+----+-----------------+
| 3  |   division 3    |
+----+-----------------+

company_divisions

+----------+--------------+  
| company  |   division   |  
+----------+--------------+ 
|     1    |       1      |
+----------+--------------+
|     1    |       2      |
+----------+--------------+
|     2    |       1      |
+----------+--------------+
|     2    |       3      |
+----------+--------------+

company_sites

+----------+------------+  
| company  |   site     |  
+----------+------------+ 
|     1    |     1      |
+----------+------------+
|     1    |     2      |
+----------+------------+
|     2    |     2      |
+----------+------------+
|     2    |     3      |
+----------+------------+

I originally thought I could select all of the sites constrained by a company.id and division.id but I have had no such luck. I have attempted sub queries:

select * 
from sites 
where id IN (select site from company_sites where company = 3)

and joins:

select s.* 
from sites s 
inner join company_sites cs on s.id = cs.site 
where cs.company = 3

but these results only relate to the company_site and not the division. I can't seem to figure out how to get the company_divisions table involved.. something like this:

select s.* 
from sites s 
inner join company_sites cs on s.id = cs.site 
inner join company_divisions cd on divisions.id = cd.division 
where cs.company = 2 AND cd.division = 3

How can I add an additional condition or query that ensures that the same company.id that was used to select the site in company_sites relates to a company.id in company_division via the division.id?

For example given company.id = 2 and division.id = 3 I would expect a result of site 2 and site 3.

Constructive criticism is always welcome.

3
  • you should have some mapping of division to sites or vice-versa in order to fetch the sites belonging to division.. Commented Dec 3, 2017 at 7:28
  • @RohitS I considered adding a divsion_site table but the problem was multiple companies can use the same division. Maybe I should cut bait and make each company live in its own database? Commented Dec 3, 2017 at 7:31
  • the final call is yours but still what if you have multiple same divisions your aim is to get all sites from a division that belong to a company. Commented Dec 3, 2017 at 7:44

3 Answers 3

2

For such tree structure, I would probably remove company_divisions and company_sites table and design it as such.

company
+----+-------------+  
| id |    name     |  
+----+-------------+ 
| 1  |  company 1  |
+----+-------------+
| 2  |  company 2  |
+----+-------------+
name should be unique, id is the primary key 

divisions
+----+-----------------+-------------+  
| id |      name       | company id  |
+----+-----------------+-------------+
| 1  |   division 1    |      1      |
+----+-----------------+-------------+
| 2  |   division 2    |      1      |
+----+-----------------+-------------+
| 3  |   division 3    |      2      |
+----+-----------------+-------------+
| 4  |   division 1    |      2      |
+----+-----------------+-------------+
id is the primary key, company id is foreign key referenced to company.id.

sites
+----+-------------+-------------+
| id |    name     | division id |
+----+-------------+-------------+
| 1  |   site 1    |      1      |
+----+-------------+-------------+
| 2  |   site 2    |      1      |
+----+-------------+-------------+
| 3  |   site 3    |      3      |
+----+-------------+-------------+
| 4  |   site 2    |      3      |
+----+-------------+-------------+
id is the primary key, division id  is foreign key referenced to divisions.id.

Using the query

SELECT 
    sites.name as `site`, 
    divisions.name as `division`, 
    company.name as `company` 
FROM sites
LEFT JOIN divisions ON sites.`division id` = divisions.id
LEFT JOIN company ON divisions.`company id` = company.id

would give

+-------------+------------+-----------+
|    site     |  division  |  company  |
+-------------+------------+-----------+
|   site 1    | division 1 | company 1 |
+-------------+------------+-----------+
|   site 2    | division 1 | company 1 |
+-------------+------------+-----------+
|   site 3    | division 3 | company 2 |
+-------------+------------+-----------+
|   site 2    | division 3 | company 2 |
+-------------+------------+-----------+

Filtering from here onward should be quite easy, just add WHERE conditions behind.

Sign up to request clarification or add additional context in comments.

1 Comment

This works well. I never thought to approach the problem from this angle. Can you recommend any good mysql books or references?
1

I would suggest this, If you can modify the structure and have separate division site mapping table. This would also allow a site to belong to multiple divisions to multiple sites.

Company Table:

+----+-------------+  
| id |    name     |  
+----+-------------+ 
| 1  |  company_1  |
+----+-------------+
| 2  |  company_2  |
+----+-------------+ 

Division Table :

+----+-------------+--------------+  
| id |    name     |  company_id  |
+----+-------------+ -------------+
| 1  |  division 1 |      1       |
+----+-------------+--------------+
| 2  |  division 2 |      2       |
+----+-------------+--------------+ 
| 3  |  division 3 |      2       |
+----+-------------+--------------+ 
| 4  |  division 4 |      3       |
+----+-------------+--------------+ 

Sites Table :

+----+----------------------+
| id |    url               |
+----+----------------------+ 
| 1  |  http:\www.url1.com  |
+----+----------------------+ 
| 2  |  http:\www.url2.com  |
+----+----------------------+
| 3  |  http:\www.url3.com  |
+----+----------------------+
| 4  |  http:\www.url4.com  |
+----+----------------------+

division_site Table :

+----+-------------+--------------+  
| id |    div_id   |  site_id     |
+----+-------------+ -------------+
| 1  |       1     |      1       |
+----+-------------+--------------+
| 2  |       1     |      2       |
+----+-------------+--------------+
| 3  |       2     |      1       |
+----+-------------+--------------+
| 4  |       2     |      3       |
+----+-------------+--------------+
| 5  |       2     |      4       |
+----+-------------+--------------+
| 6  |       3     |      1       |
+----+-------------+--------------+
| 7  |       4     |      2       |
+----+-------------+--------------+

So you can have something like :

select company.name as company_name ,division.name as division_name ,GROUP_CONCAT(sites.url) as "Site URL's" from company inner join division on division.company_id = company.id left JOIN div_sites on div_sites.div_id = division.id inner join sites on sites.id = div_sites.site_id where company.id = 1 and division.id =1 GROUP by division.id

Which would return

+----+-------------+-------------------+-----------------------+  
| company name     |    division name  |    Url's              |
+----+-------------+-------------------+------------------------
|   company_1      |    div 1          | http:\www.url1.com,   |
|                  |                   | http:\www.url2.co     |
+------------------+-------------------+-----------------------+  

2 Comments

This works well but I went ahead with the first response. Thank you for the help.
@atomSmasher its your call... but happy to put a solution.. :D
0

the code you have given in something like this, checks for company_site.company=3 ,a value that doesn't exist in your table. Similarly with company_divisions table. In fact, there is no company 3. Try for data that exists

1 Comment

I apologize, that was meant to be a generic case. I have updated the numbers to match my final example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.