Entity Framework ModelBuilder multiple joins/subquery - sql

I have been working on how to map an entity property to a column in another table using multiple joins (or a subquery), but I am really struggling to find where to start.
I have create a SQL Fiddle that demonstrates what I want to do. A User entity should contain a property called Employee that selects the name from the employee table
SET #uid = 2;
SELECT Employee.Name
FROM Employee
JOIN Company ON Employee.CompanyId = Company.Id
WHERE Company.CompanyNo = (SELECT UserEmployee.CompanyNo
FROM UserEmployee
JOIN User ON UserEmployee.UserId = User.Id
AND User.Id = #uid)
AND Employee.EmployeeNo = (SELECT UserEmployee.EmployeeNo
FROM UserEmployee
JOIN User ON UserEmployee.UserId = User.Id
AND User.Id = #uid)
http://sqlfiddle.com/#!9/cbac3/2
Basically, a User record is linked with a Employee using a relationship table (UserEmployee), however this is a 1-0 relationship.
We are not using Ids as foreign keys, instead each Employee has a EmployeeNo and has a 1-1 relationship with a Company that has it's own CompanyNo, so the composite foreign key for the UserEmployee table is made up of the Employee and Company Numbers.
I cannot link to the EmployeeId directly in the UserEmployee table as in the actual system employee records are duplicated (for history keeping reasons) and there is a third table added into the mix.
Thank you

Related

How do I write a query to display the customer who claimed maximum amount from an ERD diagram?

This is what I wrote but I am not getting the correct answer:
select top 1 customer.first_name
from customer, claims
where customer.id = claims.id
order by claims.amount_of_claim desc
GO
You are joining claim.id and customer.id. Those will never match except by accident. The number on a claims document will never match the number on your insurance card or policy except by accident.
When you write a query, the table rows are matched based only on the query expressions, not any constraints between tables. This means that the following query will try to match unrelated things:
select top 1 customer.first_name
from customer inner join claims
on customer.id = claims.id
order by claims.amount_of_claim desc
The diagram shows that a Claim is related to a Policy which in turn is related to a customer:
Claims(customer_policy_id) -> Customer_Policy(customer_id) -> Customer
You'll have to join these 3 tables in your query
select top 1 cust.first_name
from customer cust
inner join customer_policy pol on cust.id=pol.customer_id
inner join claims cl on pol.id=cl.customer_policy_id
order by cl.amount_of_claim desc
In a relational database relations are represented by tables, not foreign key constraints. A Foreign Key Constraint is used to ensure that the FK values stored in a table are valid.
On top of that, an ER diagram is not a database diagram. The entities and relations shown in an ER diagram are don't map directly to tables. For example, a many-to-many relation between eg Customer and Address in an ER diagram would have to be translated to a bridge table, CustomerAddresses(CustomerId,AddressId). After all, a table is a relation in relational theory, and CustomerAddresses defines the relation between Customer and Address.

How to query in a way that relates a name to an ID and then using that ID to sum up what comes under that ID

I'm a student learning SQL. With querying, if you are given data that you have to relate to a primary key in the same table that will then be used to identify data in another table, how do you query that? I only want a push in the right direction because I don't want to copy and paste someone's code.
For example:
You are to find out how many staff are being managed by a manager and you are to find this by using the managers first and last name (which is not the primary key). The database is below. ManagerNo and StaffID are the same.
Branch (BranchNo, ManagerNo)
Staff (staffID, fName, lName, position, BranchNo)
Thank you for your time
You would use two joins:
select s.*
from staff s join
branch b
on s.BranchNo = b.BranchNo join
staff sm
on sm.staffId = b.ManagerNo
where sm.fname = ? and sm.lname = ?;

How to link tables correctly in SQL to add roles to staff?

Currently I have a staff table with columns:
Staff_Id, first_name, Surname.
My second table is:
Id, management_role.
When I link the tables each staff member gets added to every management role. So for example a person in first table called Jim is added three times as manager, supervisor, intern and this happens for every staff.
Some things to consider that are your ID columns are primary keys for their respective tables. If not are every value in the column is unique? Also are ids not
From your description you might be using a cross join here. The thing you need is inner join so it joins the matching id's together.
So you can do
SELECT *
FROM staff_table as st
INNER JOIN management_table as mt
ON st.Staff_Id = mt.ID

Unexpected results after joining another table

I use three tables to get to the final result. They are called project_board_members, users and project_team.
This is the query:
SELECT `project_board_members`.`member_id`,
`users`.`name`,
`users`.`surname`,
`users`.`country`,
`project_team`.`tasks_completed`
FROM `project_board_members`
JOIN `users`
ON (`users`.`id` = `project_board_members`.`member_id`)
JOIN `project_team`
ON (`project_team`.`user_id` = `project_board_members`.`member_id`)
WHERE `project_board_members`.`project_id` = '5'
You can ignore last line because it just points to the project I'm using.
Table project_board_members holds three entries and have structure like:
id,
member_id,
project_id,
created_at;
I need to get member_id from that table. Then I join to users table to get name, surname and country. No problems. All works! :)
After that, I needed to get tasks_completed for each user. That is stored in project_team table. The big unexpected thing is that I got four entries returned and the big what-the-f*ck is that in the project_board_members table are only three entries.
Why is that so? Thanks in advice!
A SQL join creates a result set that contains one row for each combination of the left and right tables that matches the join conditions. Without seeing the data or a little more information it's hard to say what exactly is wrong from what you expect, but I'm guessing it's one of the following:
1) You have two entries in project_team with the same user_id.
2) Your entries in project_team store both user_id and project_id and you need to be joining on both of them rather than just user_id.
The table project_board_members represent what is called in the Entity-Relationship modelling world an "associative entity". It exists to implement a many-to-many relationship (in this case, between the project and user entities. As such it is a dependent entity, which is to say that the existence of an instance of it is predicated on the existence of an instance of each of the entities to which it refers (a user and a project).
As a result, the columnns comprising the foreign keys relating to those entities (member_id and project_id) must be form part or all of the primary key.
Normally, instances of an associative entity are unique WRT the entities to which it relates. In your case the relationship definitions would be:
Each user is seated on the board of 0-to-many projects;
Each project's board is comprise of 0-to-many users
which is to say that a particular user may not be on the board of a particular project more than once. The only reason for adding other columns (such as your id column) to the primary key would be if the user:project relationship is non-unique.
To enforce this rule -- a user may sit on the board a particular project just once -- the table schema should look like this:
create table project_board_member
(
member_id int not null foreign key references user ( user_id ) ,
project_Id int not null foreign key references project ( project_id ) ,
created_at ...
...
primary key ( member_id , project_id ) ,
)
}
The id column is superfluous.
For debugging purposes do
SELECT GROUP_CONCAT(pbm.member_id) AS member_ids,
GROUP_CONCAT(u.name) as names,
GROUP_CONCAT(u.surname) as surnames,
GROUP_CONCAT(u.country) as countries,
GROUP_CONCAT(pt.tasks_completed) as tasks
FROM project_board_members pbm
JOIN users u
ON (u.id = pbm.member_id)
JOIN project_team pt
ON (pt.user_id = pbm.member_id)
WHERE pbm.project_id = '5'
GROUP BY pbm.member_id
All the fields that list multiple entries in the result are messing up the rowcount in your resultset.
To Fix that you can do:
SELECT pbm.member_id
u.name,
u.surname,
u.country,
pt.tasks_completed
FROM (SELECT
p.project_id, p.member_id
FROM project_board_members p
WHERE p.project_id = '5'
LIMIT 1
) AS pbm
JOIN users u
ON (u.id = pbm.member_id)
JOIN project_team pt
ON (pt.user_id = pbm.member_id)

MySQL Views: Sub-Joins

I am wanting to have a view table that aggregates rows from four tables.
The first primary table is client and is just a primary key unique id and a profile_id. The second table, profile, holds all of the firstname, address, zipcode kind of information. The third table is email; there can be many email objects to one client object but there is only one email object with the primary column flagged true; the fourth table is phone - this is also a many to one relationship (there can be cellphones, homephones, fax numbers, etc...) and only one object can have the primary column flagged.
JOINing the client table with the profile table is easy as it's one to one; what I want advice on is how to go about selecting an email and phone object based on the primary column (rather than the first JOINed result).
Any resources I can be pointed to would be greatly appreciated; as I have been searching for material for a few days.
Thank you in advance!
There shouldn't really be any problems to joining email and phone too. Just join them in another straight forward join and add WHERE phone.primary = TRUE as an ordinary WHERE-claus.
The following, I think, should do it:
SELECT *
FROM client
JOIN profile
ON profile.client_id = client.id
JOIN email
ON email.client_id = client.id
JOIN phone
ON phone.client_id = client.id
WHERE phone.primary = TRUE AND
email.primary = TRUE
select whatevercolumnsyouwant
from client
join profile using (profile_id)
join email on client.profile_id = email.profile_id
and email.primary = 1
join phone on client.profile_id = phone.profile_id
and phone.primary = 1
where client.id = :whateverclientid
the key point is that ON subclauses of JOIN clauses can specify several conditions (in AND, OR, whatever) just like WHERE clauses can but with a more "specific" purpose!