SQL IN statement with multiple conditions and 3 tables - sql

I have just learned IN and NOT IN statements in SQL. I understand statements like
SELECT * FROM table1 WHERE table1.attribute IN
(SELECT table2.attribute FROM table2 WHERE attribute = condition);
My problem is I need to show 3 columns (from two different tables) using an IN (SELECT) statement with a 3rd table with a condition from that 3rd table only and another condition from one of the first two tables.
Example:
Show name(table1), class(table1), course(table2) where course LIKE "cosc%" (table 2) and grade = 'b' (table 3). I need to USE an IN statement.
My attempt:
SELECT stud.sname, stud.class, sec.course_num FROM stud, sec
WHERE sec.course_num LIKE 'COSC%'
AND stud.stno IN
(SELECT gr.student_number FROM gr WHERE gr.grade = 'B');
Table3 shares a domain with both table1 and table2. This query resulted in way too many rows, there are only 48 rows in one of these tables. I know how to do all the JOIN statements, I don't need that.

Something like this, assuming stud refers to sec:
SELECT stud.sname, stud.class, sec.course_num
FROM stud JOIN sec ON stud.sec_id = sec.id
WHERE sec.course_num LIKE 'COSC%'
AND stud.stno IN (
SELECT gr.student_number FROM gr WHERE gr.grade = 'B'
)
;
It's possible the logic needs to be adjusted and that other logic is missing.
We'll see when the question is updated with the requested detail.

Related

Execute SQL query based on results of a condition

My SQL knowledge is somewhat limited. I have 2 Select statements that returns separate sets of results. Since the tables being queried are different sets of tables for each Select statement I would like to know if it is possible to write it such that it picks which query to execute based on the result returned from a Select Statement on a completely different table, for example:
Select C.ManBtchNum from Table C
If OITM.ManBtchNum = 'Y' then
Select * from Table A
else
Select * from Table B
Apologies for using psuedocode but its the shortest way I can explain this.
I'm not sure if a Case expression can be used here. Any advice would be helpful. Thanks
I have tried both a Case as well as a Union but I'm not getting the results needed. Granted I might be doing something wrong considering my limited knowledge
As an example,
select t1.Val, t2.Val, t3.Val,
case
when(t1.Val = Something)Then (T2.Val)Else(t3.Val)
END
from tablex t1
inner join tabley t2 on t1.commonfield = t2.commonfield
inner join tablez t3 ON t1.commonfield = t3.commonfield

SQL Query returns more

I'm having a bit of a problem with a SQL Query that returns too many results. I'm fairly new to SQL so please bear with me.
Please see the following:
Table Structures
The Query that I use looks like:
SELECT TABLE_B.*
FROM
TABLE_A
JOIN
TABLE_B
ON
TABLE_A.COMMON_ID=TABLE_B.COMMON_ID
AND TABLE_A.SEQ_3C=TABLE_B.SEQ_3C
JOIN
TABLE_C
ON
TABLE_A.COMMON_ID=TABLE_C.EMPLID
WHERE
TABLE_B.ITEM_STATUS<>'C'
and TABLE_A.CHECKLIST_STATUS='I'
and TABLE_A.ADMIN_FUNCTION='ADMA'
and TABLE_A.CHECKLIST_CD='APPL'
and TABLE_A.COMMON_ID = '123456789'
and TABLE_C.ADMIT_TERM='2171'
and TABLE_C.INSTITUTION='SOMEWHERE'
I just want the results from Table_B and not what it's giving me.
Please explain this to me as I have spent 3 days on it non-stop.
What am I missing?
You want data from TABLE_B? Then select from it only and have the conditions on the other tables in your where clause.
The inner joins on the other tables serve as existence tests, I assume? Don't do that. You'd only multiply your records, just as you are doing now, only to have to dismiss duplicates later. That can cause bad performance on large tables and errors in more complicated queries. Use EXISTS or IN instead.
select *
from table_b
where item_status <> 'C'
and (common_id, seq_3c) in
(
select common_id, seq_3c
from table_a
where checklist_status = 'I'
and admin_function = 'ADMA'
and checklist_cd = 'APPL'
)
and common_id in
(
select EMPLID
from table_c
where admit_term = '2171'
and institution = 'SOMEWHERE'
);
SELECT DISTINCT TABLE_B.*
FROM
TABLE_A
JOIN
TABLE_B
ON
TABLE_A.COMMON_ID=TABLE_B.COMMON_ID
AND TABLE_A.SEQ_3C=TABLE_B.SEQ_3C
JOIN
TABLE_C
ON
TABLE_A.COMMON_ID=TABLE_C.EMPLID
WHERE
TABLE_B.ITEM_STATUS<>'C'
and TABLE_A.CHECKLIST_STATUS='I'
and TABLE_A.ADMIN_FUNCTION='ADMA'
and TABLE_A.CHECKLIST_CD='APPL'
and TABLE_A.COMMON_ID = '123456789'
and TABLE_C.ADMIT_TERM='2171'
and TABLE_C.INSTITUTION='SOMEWHERE'
This should be easy to understand without looking at all your tables and output.
Suppose you join two tables, A and B, on a column id. You only want the columns from table B, and in table B the `id' column is a unique identifier.
Even so, if in table A an id (the same id) appears five times, the join will have five rows for that id. Then you just select the columns from table B, so it will look like you got the same row five different times.
Perhaps you don't really need a join? What is your underlying problem you are trying to solve?
It's hard to answer this question without more information about why you're executing these joins. I can explain why you're getting the results you're getting, and hopefully that will allow you to solve the problem yourself.
You start, in your FROM clause, with table A. You join this table with table B on matching COMMON_ID, which, based on the tables you provide, returns three matches for the one record you have in table A. This increases your result set size to three records. Next, you join these three records with table C, on matching ID. Because all ID's are, in fact, identical, this returns nine matches for every record in your current result set: you now have 9 x 3 = 27 records in your result set.
Finally, the WHERE clause comes into effect. This clause excludes 6 out of 9 records in table C, so you have 3 of those records left. Your final result set is therefore 1 (table A) x 3 (table B) x 3 (table C) = 9 records.

Joining SQL queries with where clause

I have 2 tables in a MYSQL database wich look like this:
Klant:
ID Naam Email Soort Status
6 test test test2
7 status test test test 20
8 soort test test test
9 soort test 2 test2 Museum
Mail:
ID Content Datum Titel
1 (lots of encoded HTML) 18-03-13 test
2 (lots of encoded HTML) 18-03-13 test2
4 (lots of encoded HTML) 18-03-13 alles weer testen
(yes, I'm still testing alot^^)
Now I have a SQL query that selects all from 'Klant' with a where clause which gets the ID from a previous page:
$strSQL = "SELECT * FROM Klant WHERE ID = '".$_GET["ID"]."' ";
What I want is to JOIN this query with the following query:
SELECT ID, Titel FROM Mail;
EDIT:
From all your answers and comments I think I begin to think my question maybe is totally wrong.. I'll explain where I need it for and I might not even need JOIN? I currently have a table wich includes the data from 'Klant' which looks like this:
The meaning is that I add another table which includes all the ID's and Title's from 'Mail'. I am sorry for the confusion I may have caused with you since I wasn't that clear with my question. I hope that this may clear up what I want and you guys can maybe tell me if I even need to JOIN this or can I do something else?
I am still a student and this is the first time I've had to use JOIN and I can't figure this out. If anyone can show me how to do this or push me in the right direction it would be great!
SELECT * FROM Klant t1
JOIN
SELECT ID, Titel FROM Mail t2
ON t1.ID = t2.ID
WHERE t1.Name = 'test'
To have the desired result do the following:
SELECT * FROM Klant t1
JOIN
SELECT ID, Titel FROM Mail t2
ON t1.ID = t2.ID
And if you want to have a specific row than just add the where clause:
WHERE t1.ID = 6
or
WHERE t1.Naam = 'test'
and so on
It is difficult to see how a JOIN is applicable in the example in your question.
A JOIN let's you pull information from more than one table based on a relationship. As far as I can see, your table's don't have any way to link a row in one with a row in the other, unless SteveP is correct and your id's provide that relationship.
For example, if your klant table had a mail_id column then you could do
SELECT *
FROM klant
JOIN mail ON klant.mail_id = mail.id
and this would return a row for every matching pair of rows in the two tables. Alternatively you could use a LEFT OUTER JOIN to pull back all rows from the table on the left of the JOIN and optionally data from a matching row on the right.
If there is nothing joining the table, you can use a CROSS JOIN which will return you a full cartesian of each row in table1 with every row in table2.
Something people often confuse with a JOIN is a UNION which allows you to write 2 SELECT statements and return the result set of both combined/joined together, but these should return the same columns in each query (e.g. selecting NULL in place of the column in a query if the query doesn't pull data for that column)
I'm guess that you want to join on the ID field which is common between the tables.
select * from Klant, Mail where Klant.ID = '".$_GET["ID"]."' and Klant.ID = Mail.ID
You can also do
select * from Klant
join Mail on Mail.ID = Klant.ID
where Klant.ID = '".$_GET["ID"]."'
You can do this directly by using the following query :
select k.ID,k.Naam, k.Email,k.Soort,k.Status, m.ID,m.Titel from Klant k, Mail m where k.ID = m.ID and k.ID = '".$_GET["ID"]."'

How do I write an SQL query to identify duplicate values in a specific field?

This is the table I'm working with:
I would like to identify only the ReviewIDs that have duplicate deduction IDs for different parameters.
For example, in the image above, ReviewID 114 has two different parameter IDs, but both records have the same deduction ID.
For my purposes, this record (ReviewID 114) has an error. There should not be two or more unique parameter IDs that have the same deduction ID for a single ReviewID.
I would like write a query to identify these types of records, but my SQL skills aren't there yet. Help?
Thanks!
Update 1: I'm using TSQL (SQL Server 2008) if that helps
Update 2: The output that I'm looking for would be the same as the image above, minus any records that do not match the criteria I've described.
Cheers!
SELECT * FROM table t1 INNER JOIN (
SELECT review_id, deduction_id FROM table
GROUP BY review_id, deduction_id
HAVING COUNT(parameter_id) > 1
) t2 ON t1.review_id = t2.review_id AND t1.deduction_id = t2.deduction_id;
http://www.sqlfiddle.com/#!3/d858f/3
If it is possible to have exact duplicates and that is ok, you can modify the HAVING clause to COUNT(DISTINCT parameter_id).
Select ReviewID, deduction_ID from Table
Group By ReviewID, deduction_ID
Having count(ReviewID) > 1
http://www.sqlfiddle.com/#!3/6e113/3 has an example
If I understand the criteria: For each combination of ReviewID and deduction_id you can have only one parameter_id and you want a query that produces a result without the ReviewIDs that break those rules (rather than identifying those rows that do). This will do that:
;WITH review_errors AS (
SELECT ReviewID
FROM test
GROUP BY ReviewID,deduction_ID
HAVING COUNT(DISTINCT parameter_id) > 1
)
SELECT t.*
FROM test t
LEFT JOIN review_errors r
ON t.ReviewID = r.ReviewID
WHERE r.ReviewID IS NULL
To explain: review_errors is a common table expression (think of it as a named sub-query that doesn't clutter up the main query). It selects the ReviewIDs that break the criteria. When you left join on it, it selects all rows from the left table regardless of whether they match the right table and only the rows from the right table that match the left table. Rows that do not match will have nulls in the columns for the right-hand table. By specifying WHERE r.ReviewID IS NULL you eliminate the rows from the left hand table that match the right hand table.
SQL Fiddle

Problem with sql query

I'm using MySQL and I'm trying to construct a query to do the following:
I have:
Table1 [ID,...]
Table2 [ID, tID, start_date, end_date,...]
What I want from my query is:
Select all entires from Table2 Where Table1.ID=Table2.tID
**where at least one** end_date<today.
The way I have it working right now is that if Table 2 contains (for example) 5 entries but only 1 of them is end_date< today then that's the only entry that will be returned, whereas I would like to have the other (expired) ones returned as well. I have the actual query and all the joins working well, I just can't figure out the ** part of it.
Any help would be great!
Thank you!
SELECT * FROM Table2
WHERE tID IN
(SELECT Table2.tID FROM Table1
INNER JOIN Table2 ON Table1.ID = Table2.tID
WHERE Table2.end_date < NOW
)
The subquery will select all tId's that match your where clause. The main query will use this subquery to filter the entries in table 2.
Note: the use of inner join will filter all rows from table 1 with no matching entry in table 2. This is no problem; these entries wouldn't have matched the where clause anyway.
Maybe, just maybe, you could create a sub-query to join with your actual tables and in this subquery you use a count() which can be used later on you where clause.