SQL WHERE Query, editing an existing query - mysql

I am completing a piece of work and one of the team members who was in charge of SQL has gone on holiday.
I have the following query:
SELECT
Car.*,
Building.*,
CarType.*
FROM
Car
INNER JOIN Building ON
Car.BuildingID=Building.BuildingID
INNER JOIN CarType ON
Car.CarType=CarType.TypeID
this is returning all of the information we need it to about the cars and buildings, however, we need to edit the query so depending on the value of a field in the Request table, called status, if this field is not = 'Accepted', then do not display the information about the buildings or cars?
I have tried the following:
SELECT
Car.*,
Building.*,
CarType.*,
Requests.*
FROM
Car
INNER JOIN Building ON
Car.BuildingID=Building.BuildingID
INNER JOIN CarType ON
Car.CarType=CarType.TypeID
WHERE
Requests.Status <> 'Accepted'
However this does not work
any help would be appreciated
thank you

You are missing the Requests table from your Query. Assuming that there is a field RequestID in the Car Table your query should look like
SELECT Car.*, Building.*, CarType.*
FROM Car
INNER JOIN Building ON Car.BuildingID=Building.BuildingID
INNER JOIN CarType ON Car.CarType=CarType.TypeID
INNER JOIN Requests ON Car.RequestID = Requests.RequestID
WHERE Requests.Status = 'Accepted'
Notice I have joined the Requests table to the Car table Assuming both contain a field called RequestID

Following Query Will return only Car , Building and cartype information Where status is only 'Accepted' not other then
SELECT Car.*, Building.*, CarType.*
FROM Car INNER JOIN Building
ON Car.BuildingID=Building.BuildingID INNER JOIN CarType ON
Car.CarType=CarType.TypeID
/* add here joining of Requests Table */
WHERE Requests.Status = 'Accepted'
Update:
/* add one line from below lines into the just below where Clause
as per your Table hierarchy */
INNER JOIN Requests.ReqID= Car.ReqID
INNER JOIN Requests.ReqID= Building.ReqID
INNER JOIN Requests.ReqID= CarType.ReqID

Related

MySQL inner join query select from same table multiple times

I believe I have formed this question title correctly because I wasn't sure how to form it. As an example, I have summarized my query below.
I have an order table which saves order details like customer id, address and product ids and quantity ordered for each order in a row. So multiple inventory/product ids are saved in a single row.
so my query looks like: this is a summarized query for an easier explanation I have omitted various other fields.
SELECT customer.name,customer.address,tbl_order.order_date,tbl_order.product1_id,tbl_order.product2_id,inventory.product1_name,inventory.product2_name
FROM tbl_order
INNER JOIN customer ON tbl_order.customer_id = customer.id
INNER JOIN inventory on tbl_order.product1_id = inventory.id
INNER JOIN inventory on tbl_order.product2_id = inventory.id
where YEAR(tbl_order.order_date)='$year'
So my question is how to get the inventory details from the inventory table based on each product id from tbl_order. I am running a while loop to show all data for a year
while($row=mysqli_fetch_assoc($sql1))
I can divide this query into 2 and run the inventory query individually but then how to combine the while loop, as sometimes there could also be empty query when some products are not in order table (depending on order to order, not all products are ordered) so this doesn't work
while($row=mysqli_fetch_assoc($sql1)) and ($row1=mysqli_fetch_assoc($inv1)) and ($row2=mysqli_fetch_assoc($inv2))
and so one for 10 products
First, of all you have bad DB design and I kindly advice to normalize your DB.
Second, if you can not re-design the DB you can use multiple joins with aliases like:
SELECT
customer.name, customer.address, tbl_order.order_date,
tbl_order.product1_id, inv1.product1_name,
tbl_order.product2_id, inv2.product2_name
FROM tbl_order
INNER JOIN customer ON tbl_order.customer_id = customer.id
INNER JOIN inventory AS inv1 ON tbl_order.product1_id = inv1.id
INNER JOIN inventory AS inv2 ON tbl_order.product2_id = inv2.id
WHERE YEAR(tbl_order.order_date)='$year'

SQL Query multiple tables with records not existing in 1

So I always have trouble with this type of query. I have 2 tables and I need to combine them as 3 but I need the query to see if a record does not exist in one connection.
The design is this:
Table 1 connects to Table 2 looking for existing records. Table 1 then needs to connect to table 2 again on a different record id but looking for not existing.
My current code looks like this:
select p.ProfileId, p.OrgInd, p.OrgName, p1.OrgInd, p1.ProfileId
from profile as p inner join
ProfileRelations as pa on p.ProfileId = pa.ProfileID inner join
profile as p1 on p1.ProfileId = pa.RelProfileID
I need profile(p) to connect to PRofileRelations(pa) as it states but I then need to connect ProfileRelations(pa) back on Profile(p1) where p1.profileid does not exist in ProfileRelations(pa) looking specifically at the column RelProfileID.
This is an association table to look at related records. The Profile table holds all of my customers and I can relate them as connections. What I am looking for is show me any profile that has no related records. The code given shows me those who do have related records, I just now want to see those who have none.
Thanks.
Jayson
Visual understanding of Joins: https://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
Use a left join:
All profiles without a related relation. In this case we join the tables but we know the values for p1 and pa will be null becuase the left join will include all profiles and only keep those with a related record in the relations table.
SELECT p.ProfileId, p.OrgInd, p.OrgName, p1.OrgInd, p1.ProfileId
FROM profile as p
LEFT join ProfileRelations as pa
on p.ProfileId = pa.ProfileID
LEFT join profile as p1
on p1.ProfileId = pa.RelProfileID
WHERE PA.ProfileID is null
In the above P1 values will always be null because of the where clause.
OR uses not exists and correlated subquery
All profiles w/o a related profile relation. since we know there is no relation there is no data we need from the other tables; thus we can exclude them from the select simplifying the query and gaining performance.
SELECT p.ProfileId, p.OrgInd, p.OrgName
FROM profile as p
WHERE NOT EXISTS (SELECT *
FROM ProfileRelations as pa
WHERE p.ProfileId = pa.ProfileID)
In this we don't select the P1 table at all since there is no relation record.
First of all: You want to select profiles. So do this; select from the profiles table. You want to apply criteria (missing relations); so put this in the WHERE clause. Criteria belongs in the WHERE clause. There is no need to join.
All profiles that have no related profiles:
select *
from profile
where ProfileId not in (select ProfileID from ProfileRelations)
and ProfileId not in (select RelProfileID from ProfileRelations);
or
select *
from profile p
where not exists
(
select *
from ProfileRelations pr
where p.ProfileId in (pr.ProfileId, pr.RelProfileID)
);
All profile pairs that are not related:
select *
from profile p1
join profile p2 on p2.ProfileID <> p1.ProfileID
where not exists
(
select *
from ProfileRelations pr
where (pr.ProfileId = p1.ProfileId and pr.RelProfileID = p2.ProfileId)
or (pr.ProfileId = p2.ProfileId and pr.RelProfileID = p1.ProfileId)
);
Per your problem statement, please try this:
select p.ProfileId, p.OrgInd, p.OrgName, p1.OrgInd, p1.ProfileId
from profile as p
inner join
ProfileRelations as pa
on p.ProfileId = pa.ProfileID
where pa.RelProfileID not in (select ProfileId from profile);

How to match this using SQL?

I am using the 3 following tables:
First table
id
response
Second table
responseid
patientid
Third table
patientid
The relationship between first and second table is on id and responceid.
The relationship between third and second is on patientid.
Now I need to retrieve values from these tables like all values from first and third tables with the help of matching with patientid from second and 3rd table.
How can I do this?
Basically if all of the columns that defines their relationship are not nullable, then INNER JOIN will suffice. But if they are nullable and you still want to display all records from firstTB, you need to use LEFT JOIN instead of INNER JOIN.
SELECT a.*, b.*, c.*
FROM firstTB a
INNER JOIN secondTB b
ON a.ID = b.responceID
INNER JOIN thirdTB c
ON b.patientID = c.patientID
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
You're probably looking for INNER JOIN or JOIN in general:
SELECT
response.id,
response.responce,
patient.patientid
FROM
`response_table` as `response`
INNER JOIN
`relation_table` as `relation`
ON
relation.responceid = response.id
INNER JOIN
`patient_table` as `patient`
ON
relation.patientid = patient.patientid
try
SELECT first.*
, third.*
FROM first
INNER JOIN second ON ( second.responseid = first.id )
INNER JOIN third ON ( third.patientid = second.patientid )
;
honestly, and no insult intended, if you have difficulties in coming up with queries like this one on your own, consider some training on db basics and db development, the sooner the better (just hoping i haven't blundered myself ... ;-)).

MySQL Multiple Joins in one query?

I have the following query:
SELECT
dashboard_data.headline,
dashboard_data.message,
dashboard_messages.image_id
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
So I am using an INNER JOIN and grabbing the image_id. So now, I want to take that image_id and turn it into images.filename from the images table.
How can I add that in to my query?
You can simply add another join like this:
SELECT dashboard_data.headline, dashboard_data.message, dashboard_messages.image_id, images.filename
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
INNER JOIN images
ON dashboard_messages.image_id = images.image_id
However be aware that, because it is an INNER JOIN, if you have a message without an image, the entire row will be skipped. If this is a possibility, you may want to do a LEFT OUTER JOIN which will return all your dashboard messages and an image_filename only if one exists (otherwise you'll get a null)
SELECT dashboard_data.headline, dashboard_data.message, dashboard_messages.image_id, images.filename
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
LEFT OUTER JOIN images
ON dashboard_messages.image_id = images.image_id
Just add another join:
SELECT dashboard_data.headline,
dashboard_data.message,
dashboard_messages.image_id,
images.filename
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
INNER JOIN images
ON dashboard_messages.image_id = images.image_id
I shared my experience of using two LEFT JOINS in a single SQL query.
I have 3 tables:
Table 1) Patient consists columns PatientID, PatientName
Table 2) Appointment consists columns AppointmentID, AppointmentDateTime, PatientID, DoctorID
Table 3) Doctor consists columns DoctorID, DoctorName
Query:
SELECT Patient.patientname, AppointmentDateTime, Doctor.doctorname
FROM Appointment
LEFT JOIN Doctor ON Appointment.doctorid = Doctor.doctorId //have doctorId column common
LEFT JOIN Patient ON Appointment.PatientId = Patient.PatientId //have patientid column common
WHERE Doctor.Doctorname LIKE 'varun%' // setting doctor name by using LIKE
AND Appointment.AppointmentDateTime BETWEEN '1/16/2001' AND '9/9/2014' //comparison b/w dates
ORDER BY AppointmentDateTime ASC; // getting data as ascending order
I wrote the solution to get date format like "mm/dd/yy" (under my name "VARUN TEJ REDDY")
Multi joins in SQL work by progressively creating derived tables one after the other.
See this link explaining the process:
https://www.interfacett.com/blogs/multiple-joins-work-just-like-single-joins/

Checking whole array over a multiple JOIN

To filter a table output of selected entries from a single table i would need something like a multiple JOIN request through several tables.
I want to filter a table of people by a special column in the table. Lets say this column is "tasks." Now tasks is also another table with the column "people" and the values between those two tables are connected with an existant "join" table in the database, which is matching several IDs of one table to each ID of the other table.
Now if this would be simple as that i could just filter with an INNER JOIN and a special condition. The problem is, that the entries of the table "tasks" are connected to another table over a "join" table in the database. To simplify things lets say it is "settings". So each "task" consists of several "settings" which are connected via a join table in their IDs.
So what is the input?
I got an array of IDs, which are representing the settings-ids i do not want to be shown.
What should be the output?
As already said i want a filtered output of "people" while the filter is "settings."
I want the sql request to return each entry of the table "people" with only joined tasks that are not joining any of the "setting-ids" from the array.
I hope you can help me with that.
Thanks in advance!
Example
Settings-Table:
1. Is in progress
2. Is important
3. Has unsolved issues
Tasks-Table: (settings.tasks is the join table between many tasks to many settings)
1. Task from 01.01.2012 - JOINS Settings in 1 and 3 (In progress + unsolved issues)
2. Task from 02.01.2012 - JOINS Settings in 2 (Is important)
3. Task from 03.01.2012 - JOINS Settings in 1 and 2 (...)
People-Table: (people.tasks is the join table between many people to many tasks)
1. Guy - JOINS Tasks in 1, 2, 3 (Has been assigned to all 3 tasks)
2. Dude - JOINS Tasks in 1 (Has been assigned to the Task from 01.01.2012)
3. Girl - JOINS Tasks in 2, 3 (...)
Now there is an array passed to a sql query
[2,3] should return noone because every person is assigned in a task that was either important or had unsolved issues!
[3] would return me only the person "Girl" because it is the only one that is assigned to tasks (2 and 3) that had no unsolved issues.
I hope it is clear now. :)
SELECT DISTINCT PEOPLE.*
FROM PEOPLE INNER JOIN PEOPLE_TASKS ON PEOPLE.PERSON_ID = PEOPLE_TASKS.PERSON_ID
WHERE TASK_ID NOT IN (SELECT DISTINCT TASK_ID
FROM TASK_SETTINGS
WHERE SETTING_ID = <Id you don't want>)
EDIT (for supplying multiple setting ids you don't want)
SELECT DISTINCT PEOPLE.*
FROM PEOPLE INNER JOIN PEOPLE_TASKS ON PEOPLE.PERSON_ID = PEOPLE_TASKS.PERSON_ID
WHERE TASK_ID NOT IN (SELECT DISTINCT TASK_ID
FROM TASK_SETTINGS
WHERE SETTING_ID IN (<Id you don't want>))
First you have to join table people and table tasks with the join table, let's call it people_tasks.
select distinct p.* from people p
inner join people_tasks pt on p.people_id = pt.people_id
inner join tasks on t.tasks_id = pt.tasks_id
Then you have to join table tasks and table settings with the join table, let's call it tasks_settings. You have to join them in the current select.
select distinct p.* from people p
inner join people_tasks pt on p.people_id = pt.people_id
inner join tasks on t.tasks_id = pt.tasks_id
inner join tasks_settings ts on t.tasks_id = ts.tasks_id
inner join settings s on s.settings_id = ts.settings_id
and now you have all people connected with its tasks and its settings. Finally you need the restriction. With the people with the settings selected, you choose the others like this:
select distinct p.people_id from people p
inner join people_tasks pt on p.people_id = pt.people_id
where p.people_id not in (
select distinct p2.people_id from people p2
inner join people_tasks pt2 on p2.people_id = pt2.people_id
inner join tasks t2 on t2.tasks_id = pt2.tasks_id
inner join tasks_settings ts2 on t2.tasks_id = ts2.tasks_id
inner join settings s2 on s2.settings_id = ts2.settings_id
where s2.settings_id in (list of ids)
)