SQL join while retaining the data - mysql

I'm using an SQL join to show all my clients addresses using address_id and to check if the booking is completed(done 1=completed). The second join connects the user_id of addresses to clients (since 1 client can have more than 1 address).
Using php, if done=1 a button needs to appear but if there are any bookings under that address_id (i.e done=0) then no button apears.
select *, coalesce(b.done, 1) completed
from addresses c
left join bookings b on b.address_id = c.address_id and b.done = 0
LEFT JOIN clients d ON c.client_id=d.client_id;
I have tried all the join methods. The button is appearing correctly with the corresponding client name so the joins are working. Although, only the client.name and addresses.address ever consistently appear. I need the address_id in the button to be able to book for that address, unfortunately, when the done=0 address_id is blank.
Is there any way that I can get the same result from the joins, while also getting the address_id?

I think you want the joins the other way. Then you should list the columns that you are using explicitly:
select c.name, a.address, a.address_id, coalesce(b.done, 1) as completed
from clients c left join
bookings b
on b.client_id = c.client_id and b.done = 0 left join
addresses a
on b.address_id = a.address_id ;
Also note that I changed the table aliases so they are abbreviations for the table name -- much easier to follow than confusing aliases.

Related

SQL efficiency join on two fields or one

Let say that I have got three tables: account, contact and address. To account and contact I want to assign multiple addresses. Is it better to have two fields in address join_type and join_id and then for example running query:
SELECT a.*
FROM address a
INNER JOIN contact c ON c.id = a.join_id AND a.join_type = 'CONTACT';
and
SELECT a.*
FROM address a
INNER JOIN account ac ON ac.id = a.join_id AND a.join_type = 'ACCOUNT';
or have account_id and contact_id instead of join_type and join_id and running query:
SELECT a.*
FROM address a
INNER JOIN contact c ON c.id = a.contact_id;
and
SELECT a.*
FROM address a
INNER JOIN account ac ON ac.id = a.account_id;
or maybe even have got two seperate address tables for account and contact? The first option is the best for future if I would like e.g. have also addresses assigned to users.
SELECT a.*
FROM address a
INNER JOIN contact c ON c.id = a.contact_id;
The fact that you have multiple types of addresses should not cause any problem since the contact_id should always be unique.
I would also consider having another column in address with account_id and have another join like this:
SELECT a.*
FROM address a
INNER JOIN account a ON a.id = a.account_id;

mySQL- how to show all contact and their status by using INNER JOIN

This is my company Table
CompanyID, CompanyName
This is my Contact Table
ContactID, ContactName, CompanyID
This is my Report Table
ReportID, ReportName
This is my ReportContact Table, Many to Many Relationship
ContactID, ReportID
I want to return all ALL my CONTACTID of 1 company, include those who are not assign to any report, I also want to return the reportID that are assign to different contacts
1 contacts can be assign to many reports
1 reports can consist of many contacts
My current SQL CODE only manage to get the 2 contactID in the ReportContactTable
SELECT rc.ContactID, rc.ReportID from contact c INNER JOIN Reportcontact rc on c.ContactID = rc.ContactID Where CompanyID=1
how can Return all the contact include those not in the reportcontact table, but get the reportID at the same times?
INNER JOIN filters out those rows that are not in ReportContact. Try to use LEFT JOIN if you want all contacts from contact table.
SELECT rc.ContactID, rc.ReportID
FROM contact c LEFT JOIN Reportcontact rc
ON c.ContactID = rc.ContactID
WHERE CompanyID = 1
I'm not 100% sure I understand what you are trying to do, but if you want all rows from the contact table then you need to use an OUTER rather than INNER join.
Try changing the word INNER to LEFT.
An INNER join ensures that rows that satisfy the join condition appear in both tables.
An OUTER join says "show me all the rows in one table, plus those that satisfy the join condition from the other table". Which table shows all the rows depends on the use of the keywords LEFT and right
a left join b on a.id = b.id will show all rows from table a plus those from b which satisfy the join condition
a right join b on a.id = b.id will show all rows from table b plus those from a which satisfy the join condition

MYSQL populate foreign id with value

I have a printed table here, and I issue a query to attempt to join the tables where the Tech_id, clients_id, job_id, part_id should populate with corresponding key in their tables / column too.
Here is my query:
SELECT * FROM work_orders, technicians as tech, parts_list as parts, job_types as job, clients as client
LEFT JOIN technicians ON tech_id = technicians.tech_name
LEFT JOIN parts_list ON part_id = parts_list.Part_Name
LEFT JOIN job_types ON job_id = job_types.Job_Name
LEFT JOIN clients ON clients_id = clients.client_name
I've messed around with multiple different variations, this one seem to be syntax correct, but now I'm getting: Column 'clients_id' in on clause is ambiguous
I'm sure that it will happen for not only clients but maybe others. I want to be able to print the table as in the picture above, but with the clients listed. Is it possible to be done via one query as well? thanks.
You have two problems.
First (this might not be your problem, but that's a "good practice"), you shouldn't use SELECT *, as you could indeed have a field with same name in different tables.
This is one (of the many) good reason to avoid * in a Select clause.
Then, your main problem is that you select tables in your from clause, and then again by joining.
Problematic line :
FROM work_orders, technicians as tech, parts_list as parts, job_types as job, clients as client
So (I don't know your table structure, so they may be errors, but you've got the idea)
SELECT
w.client_id,
t.tech_name
--etc
FROM work_orders w
LEFT JOIN technicians t ON c.tech_id = t.tech_name
LEFT JOIN parts_list p ON c.part_id = p.Part_Name
LEFT JOIN job_types j ON w.job_id = j.Job_Name
LEFT JOIN clients c ON w.clients_id = c.client_name
This means that clients_id exists in multiple tables. You need to specify which one you want. So if you for example want the clients_id of the clients table, do SELECT clients.clients_id
If all the fiels listed in your question are in the clients table you could do:
SELECT clients.* FROM work_orders, technicians as tech, parts_list as parts, job_types as job, clients as client
LEFT JOIN technicians ON tech_id = technicians.tech_name
LEFT JOIN parts_list ON part_id = parts_list.Part_Name
LEFT JOIN job_types ON job_id = job_types.Job_Name
LEFT JOIN clients ON clients_id = clients.client_name

Selecting data from multiple tables, where a specific table does not contain any identifiable columns?

I have a dilemma.
Let's assume(for simplicity's sake) I have four tables, with different numbers of columns and rows, they are: users, mail, events and service.
When I receive a request, I have an ID that links on three of those tables, but with different columns it matches to.
Let's say, users matches on user_id, mail matches on user_ref and events matches on user_ref as well.
That would've been a fine query for me to write up, even with single, multiple or even all IDs.
The problem arrives on the next step I have to take, and that's the *service table.
The service table doesn't conform to the same standards of the others, thus it does not have an user_id, or user_ref that can be pulled.
What it has instead, is a *mail_ref* column, and it has the potential to contain duplicates.
My current method is trying to use an IN() method, but it only works for selecting a single user/row.
Here's my current query:
SELECT
u.Name as Name,
COUNT(m.user_ref) AS Mail_total,
e.mail_id,
COUNT(e.user_ref) AS Event_total,
COUNT(s.mail_ref) AS service_total
FROM
users u
LEFT JOIN
mail m ON m.user_ref = u.user_id
LEFT JOIN
service s ON s.mail_ref IN(e.mail_id)
LEFT JOIN
events e ON e.user_ref = u.user_id
WHERE u.user_id IN(my,list,of,ids)
GROUP BY s.mail_ref
The problem I have with it currently, is that although it's selecting the correct data, it's not selecting unique data for every id I specify.
It works marginally fine when given a single id, but as mentioned above, not when it has to retrieve multiple rows.
If anyone could help me out it would be much appreciated.
Do a subquery in the left join for service. Instead of:
LEFT JOIN
service s ON s.mail_ref IN(e.mail_id)
Try
LEFT JOIN
(select TOP 1 mail_ref from server) as S on s.mail_ref = e.mail_id
See if that works.
SELECT
u.Name as Name,
(select count(*) from mail m where m.user_ref = u.user_id) AS Mail_total,
e.mail_id,
(select count(*) from events e where e.user_ref = u.user_id) AS Event_total,
(select count(*) from
events e
inner join services s on s.mail_ref = e.mail_id
where
e.user_ref = u.user_id) as service_total
FROM
users u
WHERE u.user_id IN(my,list,of,ids)

Problem using MySQL Join

i have a MySQL SELECT query which fetches data from 6 tables using Mysql JOIN. here is the MySQL query i am using.
SELECT
u.id,u.password,
u.registerDate,
u.lastVisitDate,
u.lastVisitIp,
u.activationString,
u.active,
u.block,
u.gender,
u.contact_id,
c.name,
c.email,
c.pPhone,
c.sPhone,
c.area_id,
a.name as areaName,
a.city_id,
ct.name as cityName,
ct.state_id,
s.name as stateName,
s.country_id,
cn.name as countryName
FROM users u
LEFT JOIN contacts c ON (u.contact_id = c.id)
LEFT JOIN areas a ON (c.area_id = a.id)
LEFT JOIN cities ct ON (a.city_id = ct.id)
LEFT JOIN states s ON (ct.state_id = s.id)
LEFT JOIN countries cn ON (s.country_id = c.id)
although query works perfectly fine it sometimes returns duplicate results if it finds any duplicate values when using LEFT JOIN. for example in contacts table there exist two rows with area id '2' which results in returning another duplicated row. how do i make a query to select only the required result without any duplicate row. is there any different type of MySQL Join i should be using?
thank you
UPDATE :
here is the contacts table, the column area_id may have several duplicate values.
ANSWER :
there was an error in my condition in last LEFT JOIN where i have used (s.country_id = c.id) instead it should be (s.country_id = cn.id) after splitting the query and testing individually i got to track the error. thank you for your response. it works perfectly fine now.
Duplicating the rows like you mentioned seems to indicate a data problem.
If users is your most granular table this shouldn't happen.
I'd guess, then, that it's possible for a single user to have multiple entries in contacts
You could use DISTINCT as mentioned by #dxprog but I think that GROUP BY is more appropriate here. GROUP BY whichever datapoint could potentially be duplicated....
After all, if a user has corresponding contact records, which one are you intending to JOIN to?
You must specify this if you want to remove "duplicates" because, as far as the RDBMS is concerned, the two rows matching
LEFT JOIN contacts c ON (u.contact_id = c.id)
Are, in fact, distinct already
I think a DISTINCT may be what you're looking for:
SELECT DISTINCT
u.id,u.password,
u.registerDate,
u.lastVisitDate,
u.lastVisitIp,
u.activationString,
u.active,
u.block,
u.gender,
u.contact_id,
c.name,
c.email,
c.pPhone,
c.sPhone,
c.area_id,
a.name as areaName,
a.city_id,
ct.name as cityName,
ct.state_id,
s.name as stateName,
s.country_id,
cn.name as countryName
FROM users u
LEFT JOIN contacts c ON (u.contact_id = c.id)
LEFT JOIN areas a ON (c.area_id = a.id)
LEFT JOIN cities ct ON (a.city_id = ct.id)
LEFT JOIN states s ON (ct.state_id = s.id)
LEFT JOIN countries cn ON (s.country_id = c.id)
This should only return rows where the user ID is distinct, though you may not get all the joined data you'd hoped for.