mysql multiple NOT in where condition based on result from another query - mysql

I have a situation where in i need to pull data from one table but exclude some rows based on the rows in another table. I mean that i need to pull studentid(s) from one table but exclude those studentid(s) which are there in another table.
first query :
$sql = "select studentid from table 2 where iarsid = '12'";
as i'll get an array result from this query i want to use this result and put it in NOT conditions in the next query simply excluding these very rows from the result from this another query.
Second query:
$sql2 = "select studentid from table 2, table 3 where iarsid = '12' // and a lot of joins";
Basically the students who are in the first table are not needed while pulling out students based on the second query.
If i am using the wrong logic, please guide so as to achieve this.

You can do the general idea at least 3 ways, using a LEFT JOIN, and also using NOT IN and NOT EXISTS.
Via LEFT JOINS.
SELECT student_name
FROM table_A a
LEFT JOIN table_B b ON a.student_id = b.student_id
WHERE b.student_id IS NULL
This gets all student information in table_A, where the student is not in table_B.
and here it is via NOT EXISTS:
SELECT student_name
FROM table_A a
WHERE NOT EXISTS (SELECT student_id FROM table_B b WHERE b.student_id = a.student_id)
and via NOT IN
SELECT student_name
FROM table_A a
WHERE a.student_id NOT IN (SELECT student_id FROM table_B b)

Do you mean second query that use the first query as a condition with NOT?
"select studentid from table 2, table 3 where iarsid = '12' // and a lot of joins"
+ " WHERE studentid NOT IN (select studentid from table 2 where iarsid = '12')"

I can see that you have accepted an answer. But you can also do this. The best way to check which query is fast by checking your Explain Plan.
SELECT student_name
FROM table_A a
WHERE a.student_id NOT EXISTS (SELECT student_id FROM table_B b)
Since this is an un-correalted query using exists, this will be fater for a larger table. And IN will be faster for a small table. The reason it's faster the moment it finds no match, it will return a false instead IN will do a full table scan.
Also this one:
SELECT student_name
FROM table_A a
WHERE NOT EXISTS (SELECT null
FROM table_B b
WHERE a.studentid = b.studentid);

Related

Return rows from MYSQL table A where table_A.col_1 = table_b.col_2 without using a left outer join?

In a MySQL database with two tables table_A and table_B I want to return selected row columns from table_A based on comparison with values in table_B. The below erroneous line sums up the idea:
SELECT col_1, col_2, col_3 FROM table_A where table_A.col_1 = table_B.col_2;
I do not want any elements from table_B.
Why I can't use a left outer join: I've tried this with a left outer join as illustrated here(https://blog.codinghorror.com/a-visual-explanation-of-sql-joins/) however the database complains that the column names are ambiguous and changing table column names in the database isn't an option.
I you want rows in table_A whose col1 can be found in table_B(col_2), you can use exists:
select a.col_1, a.col_2, a.col_3
from table_A a
where exists (select 1 from table_B b where b.col_2 = a.col_1);
If you want rows that do not exist in table_B, then just change exists to not exists.
Note that I prefix the column names with the (alias of the) table they belong to. This is called qualifying the columns, and is how you avoid the ambiguous column name problem that you seemingly have met when trying to join.
If column names are ambiguous, qualify them, eg
select table_A.col_1, table_A.col_2, table_A.col_3
from table_A
join table_B on table_A.col_1 = table_B.col_2
or for brevity you can assign an aliases to tables:
select a.col_1, a.col_2, a.col_3
from table_A a
join table_B b on a.col_1 = b.col_2

Update a field in table A with the max value of field in table B

I want to update a field, let's call it 'field_A', in table 'table_A' with the maximum value that exists of field 'field_B' in 'table_B', but only IF there is a max value for that field 'field_B' in table 'table_B'.
Table 'table_B' has a 'reference' field which contains the 'id' of the table_A record we want to update.
Now I have the following query, which works perfectly.
UPDATE table_A a SET a.field_A = (SELECT MAX(b.field_B)
FROM table_B WHERE b.reference = a.id)
WHERE a.id IN (
SELECT reference
FROM table_B
GROUP BY reference
HAVING COUNT(reference) > 0
)
So it only updates field_A IF there are records found for that reference because I don't want to end up setting fields 'field_A' to zero when no related records were found.
As I said before, this query already works perfectly, but now I have to run a query for table_B two times, which seems a little bit inefficient and it is probably possible to do it with only 1 join statement but I can't seem to tackle the issue.
Since this query has to cross reference a lot, really a lot, of records, performance is really an issue here.
With these two nested statements, your UPDATE statements seems quite
inefficient to me. Try this SQL statement below, that should do the job.
SQL Fiddle here: http://sqlfiddle.com/#!2/5825a/2
UPDATE table_A a1
JOIN
(
SELECT a.id as id, max(b.field_B) as max_val
FROM
table_A a
LEFT JOIN table_B b ON a.id = b.reference
GROUP BY a.id
) t on a1.id = t.id
SET
a1.field_A = t.max_val
WHERE
(t.max_val IS NOT NULL)

how to get results based on column's result type from 2 other tables

i have a table called users contained
(Table A)
Users
user_id
username
user_type[1,2]
(Table B) if user_type=1
user_id
full_name
(Table C) if user_type=2
user_id
full_name
i want to get single record set by executing single query, is that possible in PHP mysql.
Try this:
SELECT table_a.*, COALESCE(table_b.full_name,table_c.full_name) AS full_name
FROM table_a
LEFT OUTER JOIN table_b ON table_b.user_id = table_a.user_id
LEFT OUTER JOIN table_c ON table_c.user_id = table_a.user_id WHERE 1;
It uses the LEFT OUTER JOIN, which means that it joins it to table_b on the given condition. However, for each row in table_a, whether it finds a matching row in table_b or not, it will return the table_a row. If it does not find a matching row, the table_b columns are just NULL. Same thing with table_c.
Then, we just select all the table_a columns. However, we now have two full_name columns, one from table_b and one from table_c. We use COALESCE to merge them.
COALESCE returns the first non-NULL value.
Since we know that there is either a matching row in table_b or a matching row in table_c, it is not a problem. However, it would be a problem if somehow you allows a matching row to be found in both table_b and table_c.
The risk can be mitigated by adding additional ON clause conditions to get:
SELECT table_a.*, COALESCE(table_b.full_name,table_c.full_name) AS full_name
FROM table_a
LEFT OUTER JOIN table_b
ON table_b.user_id = table_a.user_id AND table_a.user_type = 1
LEFT OUTER JOIN table_c
ON table_c.user_id = table_a.user_id AND table_a.user_type = 2
WHERE 1;
Still, you will need to make sure only 1 row is present for each user in table_b and table_c.
Instead of COALESCE you can optionally use CASE like:
SELECT table_a.*, CASE user_type WHEN 1
THEN table_b.full_name
ELSE table_c.full_name END AS full_name
...
or use an IF function like:
SELECT table_a.*, IF(user_type=1,table_b.full_name,table_c.full_name) AS full_name
...
You can UNION both tables and later on JOIN it with tableA
SELECT a.User_ID,
a.`username`,
b.full_name,
a.user_type
FROM tableA a
(
SELECT user_ID, full_name
FROM tableB
UNION
SELECT user_ID, full_name
FROM tableC
) b ON a.User_ID = b.User_ID
-- WHERE a.user_type = 1 -- add extra condition here

Select count(id) from one table where that id is present in another table MYSQL

EDIT: Detailed description
Detailed Description:
*in table_a there are 100 members but only 50 of them have records in table_b and only 25 have records in table_b where approved = 1 THEREFORE the value I will need returned by the query is 25*
Hey everyone here is the query I am trying to resolve it will need to return a single result count so I can access with mysql_result($query, 0).
SELECT COUNT(id) FROM table_a WHERE (THIS IS WHERE I AM STUCK)
I need to check if the( count of memberID in table_b WHERE memberID matching each id in table_a and approved in table_b = 1) - is greater than 1
The final result needs to be a count of the number of members that have an entry in table_b.
Sample of table columns that need to access
table_a
-----------------
id
table_b
------------------
id
memberID
approved
Let me know if you need any more details.
Problem Solved
Had to think of it backwards
SELECT COUNT( DISTINCT memberID )
FROM table_b
WHERE approved =1
I do not need to even look at table_a seeing as I am counting the memberID based on table_b
Sometimes the solution is so simple and right in front of you.
Thanks for all the help! I hope this helps other in the future.
I'm assuming you want to get the number of records in table_a that match to table_b, as long as the value in table_b is approved. Therefore, I would join the 2 tables. The inner join ensures that you only consider rows that are in both tables, and the where statement takes care of the approved requirement.
select count(a.id)
from table_a a
join table_b b
on a.id = b.memberID
where b.approved=1
SELECT b.ID, a.ID
FROM table_a a, table_b b
WHERE a.ID = b.ID AND b.ID = 1
SELECT COUNT(*) AS cnt
FROM table_a AS a
WHERE EXISTS
( SELECT *
FROM table_b AS b
WHERE b.memberID = a.id
AND b.approved = 1
)
I'm a bit rusty in SQL, but can this be achieved by specifying the two tables in the query like this:
SELECT COUNT(DISTINCT table_a.id)
FROM table_a, table_b
WHERE table_a.id = table_b.MemberID
AND table_b.approved = 1;
I believe that meets your select criteria.

SQL query to select from one table based on a condition from a different table

The first table have fields:
A_id, B_id, field1, field2
The second table have fields
C_id, A_id, B_id
I want to select all the rows in the first table that contain a B_id that is also present on the second table, moreover, I want only those rows with an specific A_id. I've tried to use JOIN statements, but I can't figure out the correct one. So far I have tried queries like this one, but they don't produce the desired result:
SELECT post.* FROM post INNER JOIN subscription ON subscription.iduser = 22 WHERE post.iduser = 22;
BTW, all of this is on MySQL.
I would write something like :
SELECT post.*
FROM post
LEFT JOIN subscription USING (iduser)
WHERE subscription.iduser = 22
If you have same field names in two tables you join , then JOIN subscription ON subscription.iduser = post.iduser can be written as JOIN subscription USING( iduser ).
Makes code a bit more readable.
update : fixed the typo