SQL Join on case for a table made using subquery - sql

I have an output from a subquery
SELECT roll, marks FROM STUDENTS WHERE std in (1,2,3,4,5,6) and belongsTo in ('A', 'B', 'C') and subject = 'maths'
which I want to join to my table only in case when the value of a column from another table is Teacher.code = 1 else I don't want this above sub table to be considered
OTHER INNER JOIN AND SELECT TABLE STATEMENT
INNER JOIN (SELECT roll, marks FROM STUDENTS WHERE std in (1,2,3,4,5,6) and belongsTo in ('A', 'B', 'C') and subject = 'maths') GRADE
ON CASE
WHEN Teacher.code = 1 THEN /* the above join should be used*/
WHEN Teacher.code= 2 THEN /* above join should not be used */

You seem to want something like this:
ON Teacher.code = 1 AND <join conditions> OR
Teacher.code = 2
Presumably, if Teacher.code is neither 1 nor 2 the ELSE 0 means you want nothing to match.

Related

SQL: Joining tables with WHERE clauses

I am trying to join two tables that share the same individual ID (key). The first table (a) is a 'wide' table with many variables including key and age, and the second table (b) is a 'long' table, including only the variables key, diagnosis_number, and diagnosis, where each individual can have multiple values of diagnosis.
I want to select columns key, age, and the primary diagnosis for individuals where:
diagnosis = "a", "b", or "c" when diagnosis_number = 1 [the 'primary diagnosis']
AND diagnosis = "y" for any of diagnosis_number = 2:20
I've tried:
SELECT main.key, main.age, diag.diagnosis
FROM a as main
INNER JOIN
(
SELECT prim.key, prim.diagnosis
FROM
(SELECT DISTICT key, diagnosis
FROM b
WHERE diagnosis IN ('a', 'b', 'c')
AND diagnosis_number = 1) as prim
INNER JOIN
(SELECT DISTICT key, diagnosis
FROM b
WHERE diagnosis = 'y'
AND diagnosis_number BETWEEN 2 AND 20) as sec
ON prim.key = sec.key) as diag
ON main.key = diag.key
Think this could be solved without subqueries/SELECTs inside of joins:
SQL Server
SELECT a.key, a.age, b.diagnosis
FROM a
INNER JOIN b
ON b.key = a.key
WHERE b.diagnosis IN ('a', 'b', 'c')
AND b.diagnosis_code = 1
AND a.key IN (SELECT b1.key
FROM b AS b1
WHERE b1.diagnosis = 'y'
AND b1.diagnosis_code BETWEEN 2 AND 20)

SQL: Find common rows in different record

I have 3 tables:
Teacher Table (t_id, email, ...)
Student Table (s_id, email, ...)
Teaching Table (t_id, s_id, class_time, ...)
I have a task which is, given two t_id, find the common students that these 2 teachers have taught.
Is it possible to accomplish this in strictly SQL? If not I might try to retrieve out the student records individually based on different teacher, and do a search to see which students they have in common. This seems a bit overkill for something that seems possible to write a SQL query for.
You can self join to get students for both teachers.
DECLARE #TeacherID1 INT = 1
DECLARE #TeacherID2 INT = 2
SELECT
StudentID = T1.s_id,
Teacher1 = T1.t_id,
Teacher1ClassTime = T1.class_time ,
Teacher2 = T2.t_id,
Teacher2ClassTime = T2.class_time
FROM
TeachingTable T1
INNER JOIN TeachingTable T2 ON T2.s_id=T1._sid AND T2.t_id=#TeacherID2
WHERE
T1.t_id = #TeacherID1
ORDER BY
T1.ClassTime
select s_id
from student a
inner join teaching b on a.s_id = b.s_id
where t_id = 'First give t_id'
INTERSECT
select s_id
from student a
inner join teaching b on a.s_id = b.s_id
where t_id = 'Second give t_id'
This work with MS DB, but probably not with others.
select s_id
from student a
inner join teaching b on a.s_id = b.s_id
where b.t_id = 'First give t_id'
and s_id in (
select s_id
from student c
inner join teaching d on c.s_id = d.s_id
where d.t_id = 'Second give t_id'
)
the second one should work with any DB.

Joining tables based on value

I'm having some hard time doing the join function on those two tables. I have simplified the example dataset as there are additional where-clauses involved for the first table however that doesn't seem to be a problem.
I would write the query for joining the two tables below:
select a.prod_code, a.prod_name, b.ref_value from Product_code a
left join Product_reference b on a.prod_code = b.pref_code
where a.prod_code <> 'CURTAIN' and b.ref_value = 'MAN'
The problem I'm facing is that I want to join tables kind of conditionally. I.e. if the ref_type value is 'MAN' in Product_reference table, I do want to join it, otherwise not.
For an example this query would not include "Chair" in the result as it does not have an ref_type 'MAN' available in the "Product_name". What I'd need though is still show it in the query result, just without joined value from the Product_reference table (given that value with ref_type 'MAN' does not exist for it), not leave it out altogether.
Meanwhile Product_name table record 'CURTAIN' should be left off (regardless if Product_reference ref_type 'MAN' exists or not)
Any recommendations?
Product_code
prod_code prod_name
A Table
B Chair
C Window
D Door
E Curtain
Product_reference
pref_code ref_type ref_value
A MAN x
A AUTO y
B AUTO z
C AUTO z1
C MAN x1
D AUTO zxc
E AUTO abc
E MAN cba
Move b.ref_value = 'MAN' to the join predicate:
SELECT a.prod_code, a.prod_name, b.ref_value
FROM Product_code a
LEFT JOIN Product_reference b ON a.prod_code = b.pref_code AND b.ref_value = 'MAN'
WHERE a.prod_code <> 'CURTAIN'
This will accomplish what you want, which is only left joining the data from table b where b.ref_value = 'MAN', instead of removing all other rows from the result set altogether.
Side note, thanks for including your query and sample data in your very well made question. We appreciate it.
you could use a inner join on the distinct product that have 'MAN'
select
a.prod_code
, a.prod_name
, b.ref_value
from Product_code a
inner join (
select distinct pref_code
from Product_reference
where ref_type = 'MAN') t2 on t2.pref_code = a.prod_code
and a.prod_code <> 'CURTAIN'

Oracle Statement does not count correctly

I've got a SQL-statement with a - for me not explainable - strange behaviour.
Perhaps you could find what's wrong:
When I use the statement
select count(*) from department
I got 2755 results
Using the following statement
select
building1.street, building1.streetno, building1.plz, building1.city, dept1.buildingid
from
department dept1
left join
supporter sup
on
dept.supporterid = sup.id
left join
building building1
on
sup.buildingid = building1.ibuildingid
where
dept.usepostaladresssupporter = 1
union all
select
building2.street, building2.streetno, building2.plz, building2.city, dept2.buildingid
from
building building2
right join
tueks_department dept2
on
dept2.buildingid = building2.ibuildingid
where
dept2.usepostaladresssupporter = 0
I got 2755 results too.
But when I want to combine the two statements with a left join:
select count(*) from department
left join
(
select
building1.street, building1.streetno, building1.plz, building1.city, dept1.buildingid
from
department dept1
left join
supporter sup
on
dept.supporterid = sup.id
left join
building building1
on
sup.buildingid = building1.ibuildingid
where
dept.usepostaladresssupporter = 1
union all
select
building2.street, building2.streetno, building2.plz, building2.city, dept2.buildingid
from
building building2
right join
tueks_department dept2
on
dept2.buildingid = building2.ibuildingid
where
dept2.usepostaladresssupporter = 0
) postadress
on
department.buildingid = postadress.buildingid;
I got 3648513 results.
My expectation was, that I get only 2755 results.
Where's the mistake?
Thanks for help!
I assume that buildingid is not unique (for my reasoning to hold true, it can't be unique)
Imagine following simple tables
TableA
create TableA (name VARCHAR(32));
insert into TableA values ('Lieven');
insert into TableA values ('Lieven');
TableB
create TableB (name VARCHAR(32));
insert into TableB values ('Lieven');
insert into TableB values ('Lieven');
insert into TableB values ('AnyOtherValue');
Select statement
select * from TableA a left outer join TableB b on a.name = b.name
As each record of TableA is matched with each record of TableB where the name is equal, this will result in 4 records (the AnyOtherValue is dissmissed as it doesn't match)
The first record of TableA is returned with two of three records of `TableB'
The second record of TableA is returned with two of three records of `TableB'
The query
select
building1.street, building1.streetno, building1.plz, building1.city, dept1.buildingid
from
department dept1
left join
supporter sup
on
dept.supporterid = sup.id
left join
building building1
on
sup.buildingid = building1.ibuildingid
where
dept.usepostaladresssupporter = 1
union all
select
building2.street, building2.streetno, building2.plz, building2.city, dept2.buildingid
from
building building2
right join
tueks_department dept2
on
dept2.buildingid = building2.ibuildingid
where
dept2.usepostaladresssupporter = 0
will return one row per department that has usepostaladresssupporter as either 0 or 1 (note that records with other values will not be included, this may or may not be a problem depending on the constrainst of this column).
The unique key of this query results is probably something like departmentid (you will need to include that column in your select criteria).
So the correct query should look something like this:
select * from department
left join
(
select
building1.street, building1.streetno, building1.plz, building1.city, dept1.departmentid
from
department dept1
left join
supporter sup
on
dept.supporterid = sup.id
left join
building building1
on
sup.buildingid = building1.ibuildingid
where
dept.usepostaladresssupporter = 1
union all
select
building2.street, building2.streetno, building2.plz, building2.city, dept2.departmentid
from
building building2
right join
tueks_department dept2
on
dept2.buildingid = building2.ibuildingid
where
dept2.usepostaladresssupporter = 0
) postadress
on
department.departmentid = postadress.departmentid;
Your query will go wrong on data something like this:
Departmentid BuildingId Name
1 1 Dept1
2 2 Dept2
3 2 Dept3
The multiplying effect is not quite equal to deptcount * deptcount, but rather it is buildingcount * buildingcount + deptcount - buildingcount

selecting qualified records from a group

There are 2 tables. 1 is the primary table and the other has a 1 to many relationship with the primary table. The table with the many relationship has a field that is being used as a flag. So it usually have a value of Y or null.
So I'd like to select rows from the primary table that has records in the 2nd table only if all the rows on the 2nd table has a Y in its field. In other wards, if the Y field has a null or some other value, they don't qualify.
So the logic is if all rows have a Y than, OK, if some rows have yes and some do not have Y, than they don't qualify in the selection.
Hope that's clear.
Thank you.
Something like this should do the trick...
SELECT p.Field
FROM PrimaryTable p
WHERE NOT EXISTS(SELECT * FROM SecondaryTable s WHERE p.ID = s.ID AND (s.Flag <> 'Y' OR s.Flag IS NULL))
I've assumed that either there will always be a record in SecondaryTable for a given PrimaryTable record....OR, if not, then you still want the primary record returned.
SELECT
p.*
FROM
PrimaryTable p,
( select s.ID,
count(*) AllRecs,
sum( case when S.Flag = 'Y' then 1 else 0 end ) as YesRecCount
from
SecondaryTable s
group by
s.ID
having
AllRecs = YesRecCount ) squalified
WHERE
p.ID = squalified.ID
select p.*
from primary_table p
inner join secondary_table s
on p.join_key = s.join_key
and s.flag = 'Y'
where not exists(select null from secondary_table s2 where s2.join_key = p.join_key and (s2.flag is null or s2.flag <> 'Y'))