This question already has an answer here:
LEFT JOIN does not return all the records from the left side table
(1 answer)
Closed 4 years ago.
I have four tables.
Level Table levels(id, name)
Student Table students(id, name, level_id)
Subject Table subjects(id, name)
Report Table reports(id, student_id, subject_id, test, exam)
I need a single query that will fetch results(report table) for a single level(e.g id=1 for Class One) and a particular subject(e.g id=2 for like English)
I have this query:
select name, test, exam
from `reports`
right join `students`
on `reports`.`student_id` = `students`.`id`
where `students`.`level_id` = '1'
and `reports`.`subject_id` = '2'
But it's only showing result for records that are inside the reports table. Am expecting all data from the students table where the level_id is specified but with NULL from their test and exam row if they don't have record in the results table.
The main issue is the subject_id clause(and reports.subject_id = '2') on the query. It's only working for record if present in the records table Here is the result
When I used subject_id that's not in the result table Here is the result -not returning anything
But it's only showing result for records that are inside the reports table
Not strictly true - its only showing results where reports.subject_id = '2'. If there is no matching row in the reports table, then the subject_id would be null, and null is not equal to 2.
You need to specify the predicate for the reports table in the join clause, not in the where clause, to get all the students:
select name, test, exam
from `reports`
right join `students`
on `reports`.`student_id` = `students`.`id`
and `reports`.`subject_id` = '2'
where `students`.`level_id` = '1'
you can try below statement to get all student with level=1
select name
, test
, exam
from students
join reports
on students.id = reports.student_id
and reports.subject_id = 2
where students.level_id = 1
Related
I have 2 tables, countries and users
users
id
country_id
1
1
2
1
3
1
4
2
5
2
countries
id
monthly_count
1
0
2
0
I want to update the monthly_count column in countries table by counting rows in users table grouped by country_id in a single update query. So after updating the countries table will look like this:
countries
id
monthly_count
1
3
2
2
The query I ended up with is:
UPDATE countries c
SET c.monthly_count = (
SELECT COUNT(u.country_id) FROM users u
WHERE u.country_id = c.id
GROUP BY u.country_id
);
The query is working as expected. It is updating the monthly_count column of every row in the countries table with corresponding correct count values for each country_id group from users table.
However, I am not sure how the query is working. The main question I have is, how the result of subquery is assigned to the correct row? Is the subquery executed one time and returning all the group by count values for each country_id at once or, is the sub query being executed each time for every row in countries table?
I would write this an update join:
UPDATE countries c
INNER JOIN
(
SELECT country_id, COUNT(*) AS cnt
FROM users
GROUP BY country_id
) u
ON u.country_id = c.id
SET c.monthly_count = u.cnt;
That being said, the monthly counts are aggregate data, and you might want to consider not doing this update or storing this data. So, I am happy with the following query or view:
SELECT c.id, COUNT(u.cnt) AS monthly_count
FROM countries c
LEFT JOIN users u
ON u.country_id = c.id
GROUP BY c.id;
i have a question about sql query.
here i have 3 table which are:
Table : elaun
1. elaun_kod (pk)
2. Jenis_elaun
3. peratus_elaun
table 2 : staff_elaun
1. staff_elaunID (pk)
2. staff_ID (fk)
3. elaun_kod (fk)
table 3 : staff
1. staff_ID (pk)
So here, i want to select the 'jenis_elaun'and 'peratus_elaun' from elaun table where their 'jenis_kod' equal to 'jenis_kod' in staff_elaun table. And then from staff_elaun table, i want to compare staff_ID with staff_ID in staff table.
so here is my query but its didnt display anything
$sql1 = mysql_query("
SELECT elaun.*
FROM elaun, staff_elaun, staff
WHERE
elaun.elaun_kod = staff_elaun.elaun_kod
AND staff_elaun.staff_ID = staff.staff_ID
AND staff.staff_ID = '$data[staff_ID]'
");
You are describing a series of joins between tables. Each join has a condition for which rows correspond in each table.
In SQL, that is specified with a JOIN clause.
SELECT
elaun.*
FROM elaun
INNER JOIN staff_elaun USING (elaun_kod)
INNER JOIN staff USING (staff_ID)
Then, apply the restriction using a WHERE clause.
SELECT
elaun.*
FROM elaun
INNER JOIN staff_elaun USING (elaun_kod)
INNER JOIN staff USING (staff_ID)
WHERE
staff.staff_ID = '… the ID value you want here …'
Of course, you should not be directly injecting values into the query; instead, use query parameters. See How can I prevent SQL injection in PHP?
i'm running into a complex problem, the data in a db has three tables.
First_DB
-- default_users
id username email password
1 Timbog Timbog#mail.com vads7y3kkjdfa
2 Marta Marta#mail.com vads7y3kkjdfa
-- default_album
album_id album_name default_user_id
1 Name_Tim 1
3 Katarina 2
-- default_album_img
img_id image_file album_id
3 1320229733.jpg 1
4 3320229733.jpg 3
Second_DB
--users
user_id user_name user_email user_pass user_image
1 Timbog Timbog#mail.com vads7y3kkjdfa 1320229733.jpg
2 Marta Marta#mail.com vads7y3kkjdfa 3320229733.jpg
The approach i used to solve this problem is to first fetch all data by inner join, should i use full outer join and insert the required field to my table, the following query is actual by which i'm trying to make it wor:
INSERT INTO bbpin.users ( user_name, user_pin, user_email, user_password, user_img)
SELECT default_users.username, default_users.bb_pin, default_users.email, default_users.password
FROM bbmpins_pins.default_users
INNER JOIN bbmpins_pins.default_album_images
ON default_album_images.album_id = default_users.id;
i miss the thing how do i compare two table's id in this join maybe? or this query is all wrong by approach?
By two tables which are sepearte in First_DB there could be multiple record how do we trunk them to last entry only ?
Thanks
It looks like you are attempting to retrieve all rows from the default_users table. And along with each row, also return the corresponding row(s) from default_album table. And along with that, the corresponding row(s) from default_album_img table.
Given the example data, a query using inner joins would return the specified result:
SELECT u.id AS user_id
, u.username AS user_name
, u.email AS user_email
, u.password AS user_pass
, i.image_file AS user_image
FROM default_users u
JOIN default_album a
ON a.default_user_id = u.id
JOIN default_album_img i
ON i.album_id = a.album_id
That query will work for the example data.
But, if there is a row in default_user which doesn't have a matching row in default_album, then an inner join won't return that row:
-- default_users
id username email password
3 branstark bran#winterfell warg2
Or, if there are two or more rows in default_album that match a given user, then the query will return two copies of the row from default_user...
-- default_album
album_id album_name default_user_id
1 Tim2 1
Without a specification of what is to be returned in those cases, we can't recommend a query.
I don't see anything wrong with your current approach using a JOIN but could modify it a bit to be more readable and also you will have to join the relation table
INSERT INTO bbpin.users (user_id, user_name, user_pin, user_email, user_password, user_img)
SELECT du.id,
du.username,
du.bb_pin,
du.email,
du.password,
dai.image_file
FROM bbmpins_pins.default_users du
JOIN bbmpins_pins.default_album da ON du.id = da.default_user_id
INNER JOIN bbmpins_pins.default_album_images dai
ON dai.album_id = da.album_id;
I am trying to optimise my php by doing as much work on the MySQL server as possible. I have this sql query which is pulling data out of a leads table, but at the same time joining two tags tables to combine the result. I am looking to add a company which is linked through a relations table.
So the table that holds the relationship between the two is relations_value which simply states (I add example data)
parenttable (companies) | parentrecordid (10) | childtable (leads) | childrecordid (1)
the companies table has quite a few columns but the only two relevant are;
id (10) | companyname (my company name)
So this query currently grabs everything I need but I want to bring the companyname into the query:
SELECT leads.id,
GROUP_CONCAT(c.tag ORDER BY c.tag) AS tags,
leads.status,
leads.probability
FROM `gs_db_1002`.leads
LEFT JOIN ( SELECT *
FROM tags_module
WHERE tagid IN ( SELECT id
FROM tags
WHERE moduleid = 'leads' ) ) as b
ON leads.id = b.recordid
LEFT JOIN `gs_db_1002`.tags as c
ON b.tagid = c.id
GROUP BY leads.id,
leads.status,
leads.probability
I need to be able to go into the relations_values table and pull parenttable and parentrecordid by selecting childtable = leads and childrecordid = 1 and somehow join these so that I am able to get companyname as a column in the above query...
Is this possible?
I have created a sqlfiddle: sqlfiddle.com/#!2/023fa/2 So I am looking to add companies.companyname as column to the query.
I don't know what your primary keys and foreign keys are that link each table together.. if you could give a better understanding of what ID's are linked to eachother it would make this a lot easier... however i did something that does return the correct result... but since all of the ID's are = 1 then it could be incorrect.
SELECT
leads.id, GROUP_CONCAT(c.tag ORDER BY c.tag) AS tags,
leads.status, leads.probability, companyname
FROM leads
LEFT JOIN (
SELECT * FROM tags_module WHERE tagid IN (
SELECT id FROM tags WHERE moduleid = 'leads' )
) as b ON leads.id = b.recordid
LEFT JOIN tags as c ON b.tagid = c.id
LEFT JOIN relations_values rv on rv.id = b.recordid
LEFT JOIN companies c1 on c1.createdby = rv.parentrecordid
GROUP BY leads.id,leads.status, leads.probability
I'm sure this is simple but my brain just isnt working today!
I have a table products, lets just assume it contains p_id, i have another table - a pivot table - which references between products and another table attributes, this table is products_to_attributes and contains pta_aid (attribute id) and pta_pid (product id)
Hopefully this (incorrect) query will show what i want to do better than i can explain it:
SELECT `p_id` FROM `products`
LEFT JOIN `products_to_attributes` ON (`pta_pid` = `p_id`)
WHERE ((`pta_aid` = '1' OR `pta_aid` = '2') AND(`pta_aid` = '3'))
I want to be able to group together attributes where a product must have attribute 1 Or attribute 2 AND have attribute 3.
If I understand your need correctly, you pretty much have to have two EXISTS clauses:
SELECT p_id FROM products PR
WHERE EXISTS (SELECT p_id FROM products_to_attributes WHERE (pta_aid = 1 OR pta_aid=2) AND pta_pid=PR.p_id )
AND EXISTS (SELECT p_id FROM products_to_attributes WHERE pta_aid = 3 AND pta_pid=PR.p_id)
SELECT p.`p_id` FROM `products` p
LEFT JOIN `products_to_attributes` pta ON (p.`p_id` = pta.`pta_pid`)
Name the tables and specify which field is from which table. However how a field can be both 1 and 3 in a row? there is a logical problem in your where clause.