Select from another table based on condition - sql

I am new to SQL Server and SQL queries. These are my three tables:
Primary keys
Table 1: CaseId
Table 2: ID
Table 3: parentId
In table 3 - if the parent is a father then the status code is 8 and if the parent is a mother then the status code is 10
I want to write a select query where I can get an output like the following:
Please help me, thanks in advance

You must join twice both tables table2 and table3:
select
t1.caseid, t1.caseName,
t3f.name fathername, t3f.email fatheremail,
t3m.name mothername, t3m.email motheremail
from table1 t1
left join table2 t2f on t2f.caseId = t1.caseId
inner join table3 t3f on t3f.parentid = t2f.parentid and t3f.gendercode=8
left join table2 t2m on t2m.caseId = t1.caseId
inner join table3 t3m on t3m.parentid = t2m.parentid and t3m.gendercode=10
See the demo

You should be able to use two sub queries from Table3 where one is for father and the other is for mother. then you can join them with case and case-parent mapping tables to get the desired output,
SELECT
C.CaseID, C.CaseName, F.Name AS FatherName, F.Email AS FatherEmail,
M.Name AS MotherName, M.Email AS MotherEmail
FROM
Table1 C
INNER JOIN
Table2 CP C.CaseID = CP.CaseID
INNER JOIN
(SELECT * FROM TABLE3 WHERE GENDERCODE = 8) F ON F.ParentID = CP.ParentID
INNER JOIN
(SELECT * FROM TABLE3 WHERE GENDERCODE = 10) M ON M.ParentID = CP.ParentID

You can do this with joins but it is a little more complicated than you might expect. A CTE helps:
with p as (
select t2.caseid, t3.*
from table2 t2 join
table3 t3
on t2.parentid = t3.parentid
)
select t1.*,
f.name as fathername, f.email as fatheremail
m.name mothernaem, m.email as motheremail
from table1 t1 left join
p pf
on t1.caseid = pf.caseid and pf.gendercode = 8 left join
p pm
on t1.caseid = pm.caseid and pm.gendercode = 10;
That said, conditional aggregation as proposed by fa06 also works.

you can use conditional aggregation with case when expression
select caseid,casename,max(case when gendercode=8 then name end) as fathername
MAX(case when gendercode=8 then email end) as fatheremail,
MAX(case when gendercode=10 then name end) as mothername,
MAX(case when gendercode=10 then email end) as motheremail
from
(
select b.caseid,c.casesname,gendercode,name,email
from table3 a inner join table2 b on a.parentid=b.parentid
inner join table1 c on b.caseid=c.caseid
)A group by caseid,casename

You can try like following. To combine two rows (mother and father), you can use MAX aggregate function using GROUP BY
SELECT caseid,
casename,
Max(fathername) AS fathername,
Max(fatheremail) AS fatheremail,
Max(mothername) AS mothername,
Max(motheremail) AS motheremail
FROM (SELECT t1.caseid,
t1.casename,
CASE
WHEN gendercode = 8 THEN t3.NAME
ELSE NULL
END AS fathername,
CASE
WHEN gendercode = 8 THEN t3.email
ELSE NULL
END AS fatheremail,
CASE
WHEN gendercode = 10 THEN t3.NAME
ELSE NULL
END AS mothername,
CASE
WHEN gendercode = 10 THEN t3.email
ELSE NULL
END AS motheremail
FROM table1 t1
INNER JOIN table2 t2
ON t1.caseid = t2.caseid
INNER JOIN table3 t3
ON t2.parentid = t2.parentid
WHERE t3.gendercode IN( 8, 10 ))t
GROUP BY caseid,
casename

Related

How to join 2 tables without creating duplicated rows of records in SQL

I have 2 tables (Table 1 and Table 2) which I would like to join and get the records of ALL dates..
I tried left join on Table1.productid = Table2.productid but it does not give me the expected output that I want..
Does anyone have experience in solving this type of join in SQL?
Use UNION ALL
SELECT
t1.Date_id,
t1.Product_id,
t1.Clicks,
0 AS Sales
FROM table1 t1
UNION ALL
SELECT
t2.Date_id,
t2.Product_id,
0 AS Clicks,
t2.Sales
FROM table2 t2
Yes you can do a full outer join to get the output as follows
select case when a.date_id is null then b.date_id end as date_id
,case when a.product_id is null then b.product_id else a.product_id end as product_id
,case when a.clicks is null then 0 else a.clicks end as clicks
,case when b.sales is null then 0 else b.sales end as sales
from table1 a
full outer join table2 b
on a.product_id=b.product_id
and a.date_id=b.date_id
Something like this may work:
INSERT INTO Your_new_table3(DateId, ProductId, Clicks, Sales)
SELECT * FROM Table1
UNION ALL
SELECT * FROM Table2;
You can use Outer Apply . Read Microsoft doc about this.
SELECT
t1.Date_id,
t1.Product_id,
t1.Click,
t2.Sales
FROM
table1 t1
OUTER APPLY
(
SELECT TOP 1 *
FROM table2 t2
WHERE t2.productid = t1.productid
) t2
OR use Group by statement :
SELECT DISTINCT
String_agg(t1.Date_id,'-'),
t1.Product_id,
t1.Click,
t2.Sales
FROM table1 t1
LEFT JOIN table2 t2 ON t2.productid = t1.productid
Group by t1.Product_id,
t1.Click,
t2.Sales
OR sue Distinct statement :
SELECT DISTINCT
t1.Date_id,
t1.Product_id,
t1.Click,
t2.Sales
FROM table1 t1
LEFT JOIN table2 t2 ON t2.productid = t1.productid

How to select and compare the values in select query in then clause

I am Getting Group 1,Product,ID from From t2 OI Join t3 OPL ON OI.c1 = OPL.P1 join t4 sp on sp.c2 = OI.p2 where sp.ID ='IQ')
It works for Group1 and Product but with Id i am facing issue
I want to compare the ID with R.ID and then i need to retrieve the value
How can i do that?
(SELECT Top 1 (CASE WHEN Group1='p'
THEN (Case when Product='10'
THEN(Select top 1 Email from t1 as R join t2 as E
on R.C1=E.E1 where R.ID=ID
)
ELSE (Select top 1 Email from t1 as R join t2 as E
on R.B1=E.E1 where R.ID=ID
)
END)
ELSE
(Select top 1 Email from t1 as R join t2 as E
on R.A1=E.E1 where R.ID=ID
)
END) AS Email
From t2 OI
Join t3 OPL ON OI.c1 = OPL.P1
join t4 sp on sp.c2 = OI.p2
where sp.ID ='IQ')

sql union displays duplicates

image of what I want
I have tried the join on x or y and it didn't work, even the group by didn't work.
What almost gave me the result is the query below
SELECT A.Id ,A.AccNo ,A.Name ,B.Id ,B.AccNo1 ,B.AccNo2 ,B.Name
from Table1 as A
left outer join Table2 as B on A.AccNo = B.AccNo1
union
SELECT A.Id ,A.AccNo ,A.Name ,B.Id, B.AccNo1, B.AccNo2, B.Name,
from Table1 as A
left outer join Table2 as B on A.AccNo = B.AccNo2
After getting the query correct I want to show only the exceptions where there was no link between the tables and its kind of difficult if the T1.ID is repeated
You seem to want a left join:
select t1.*, t2.*
from table1 t1 left join
table2 t2
on t1.id in (t2.accno1, t2.accno2);
Try:
SELECT A.Id ,A.AccNo ,A.Name ,B.Id ,B.AccNo1 ,B.AccNo2 ,B.Name
from Table1 as A
left outer join Table2 as B
ON A.AccNo = (CASE WHEN A.AccNo = B.AccNo1 THEN B.AccNo1 ELSE B.AccNo2 END)
You may nest your original query, and then use max aggregate function with grouping :
SELECT Id ,AccNo ,Name, max(Id2) as Id2, max(Name2) as Name2,
max(AccNo1) as AccNo1, max(AccNo2) as AccNo2
FROM
(
SELECT A.Id ,A.AccNo ,A.Name ,B.Id Id2 ,B.AccNo1 ,B.AccNo2 ,B.Name Name2
from Table1 as A
left outer join Table2 as B on A.AccNo = B.AccNo1
union
SELECT A.Id ,A.AccNo ,A.Name ,B.Id Id2, B.AccNo1, B.AccNo2, B.Name Name2
from Table1 as A
left outer join Table2 as B on A.AccNo = B.AccNo2
) q
GROUP BY Id ,AccNo ,Name;
SQL Fiddle Demo
Do a LEFT JOIN to return the table1 values along with matching table2 values (where t2.accno2 = t1.accno):
select t1.*, t2.*
from table1 t1
left join table2 t2
on t1.accno = t2.accno2
Or, perhaps you want table2 values for matching accno1's as well?
select t1.*, t2.*
from table1 t1
left join table2 t2
on t1.accno in (t2.accno1, t2.accno2)
It this way to resolve:
SELECT
t1.id,
t1.accno,
t1.name,
(
SELECT DISTINCT
id
FROM
table2
WHERE
accno2 = t1.accno
),
(
SELECT DISTINCT
name
FROM
table2
WHERE
accno2 = t1.accno
),
(
SELECT DISTINCT
accno1
FROM
table2
WHERE
accno2 = t1.accno
),
(
SELECT DISTINCT
accno2
FROM
table2
WHERE
accno2 = t1.accno
) FROM
table1 t1
LEFT JOIN table2 t2 ON t1.accno = t2.accno1 OR t1.id = t2.id

How to join between three tables using a subquery?

I have 3 SQL tables:
tb1: name id and phone of student
tb2: courseName,courseNum
tb3: id,courseNum,grade
I need to find the name and courseName of student that their grade>80
I tried:
select * from tb1 where taz in(
select taz from tb3 where grade>80
)
and
select courseNum from tb2 where courseName in(
select * from tb3 where grade>80
)
It works but how can I join the 2 subquery?
Try using join as below:
SELECT *
FROM tb3 t3 INNER JOIN tb2 t2
ON t3.courseNum = t2.courseNum
INNER JOIN tb1 t1
ON t2.id = t1.id
WHERE t3.grade > 80
Try this :
SELECT c.name, b.courseName, a.grade
FROM tb3 a
JOIN tb2 b ON a.courseNum = b.courseNum
JOIN tb1 c ON a.id = c.id
WHERE a.grade > 80
Following query will give you the required result:
SELECT t1.Name, t2.CourseName, t3.grade from tb3
INNER JOIN tb2 t2 ON t3.CourseNum = t2.CourseNum
INNER JOIN tb1 t1 ON t1.id = t3.Id
where t3.grade > 80
SMA answer is true, but need little modification.
first: condition on second ON should be: t3.id = t1.id
second: we want name and courseName.
SELECT t1.name, t2.coursename
FROM tb3 t3 INNER JOIN tb2 t2
ON t3.courseNum = t2.courseNum
INNER JOIN tb1 t1
ON t3.id = t1.id
WHERE t3.grade > 80

Alternative for union in Oracle

Is there any alternate way to fetch the following data without using union?
select A.name,A.age,B.Address,C.phoneNo from table1 A,Table2 B,Table3 C where a.pkId = b.FkId and b.pkId = c.FkId
union
select A.name,A.age,B.Address,C.phoneNo from table4 A,Table5 B,Table3 C where a.pkId = b.FkId and b.pkId = c.FkId
I am using this in Hibernate and unfortunately hibernate doesnt support Union. I was just wondering if there is any other way to achieve it else ill have to write it in a procedure and save the data in temp table and fire a sql to read data from that temp table
There is an alternative for union, but it is not pretty:
select distinct coalesce(x1.name, x2.name) as name,
coalesce(x1.age, x2.age) as age,
coalesce(x1.Address, x2.Address) as age,
coalesce(x1.phoneNo, x2.phoneNo) as age,
from (select A.name, A.age, B.Address, C.phoneNo
from table1 A join
Table2 B
on a.pkId = b.FkId join
Table3 C
on b.pkId = c.FkId
) x1 full outer join
(select A.name, A.age, B.Address, C.phoneNo
from table4 A join
Table5 B
on a.pkId = b.FkId join
Table3 C
on b.pkId = c.FkId
) x2
on 1 = 0; -- always false
I can't imagine why you would want to express a union like this. I would highly recommend, though, that you start using proper, explicit join syntax.
is this working ?
SELECT
CASE DISTINCT_FLG WHEN 1 THEN nameA ELSE nameB END name,
CASE DISTINCT_FLG WHEN 1 THEN ageA ELSE ageB END age,
CASE DISTINCT_FLG WHEN 1 THEN AddressA ELSE AddressB END Address,
CASE DISTINCT_FLG WHEN 1 THEN phoneNoA ELSE phoneNoB END phoneNo
FROM (
SELECT
T1.name AS nameA, T1.age AS ageA, T2.Address AS AddressA, T3.phoneNo AS phoneNoA,
T4.name AS nameB, T4.age AS ageB, T5.Address AS AddressB, T3.phoneNo AS phoneNoB,
ROW_NUMBER() OVER(PARTITION BY T1.name, T1.age, T2.Address, T4.name, T4.age, T5.Address, T3.phoneNo ORDER BY NULL) AS DISTINCT_FLG
FROM
table1 T1,
table2 T2,
table4 T4,
table5 T5,
table3 T3
WHERE
T1.pkId = T2.FkId AND
T4.pkId = T5.FkId AND
(
T2.pkId = T3.FkId OR
T5.pkId = T3.FkId
)
) WHERE DISTINCT_FLG IN (1, 2)
Those two UNION parts have Table3 C in common, so we can join the rest to it. To emulate UNION records from the source table can be replicated through unconditional cross join of an auxiliary table with the required number or rows:
Select Distinct
CASE R.r WHEN 1 THEN A1.name ELSE A2.name END As name ,
CASE R.r WHEN 1 THEN A1.age ELSE A2.age END As age ,
CASE R.r WHEN 1 THEN B1.Address ELSE B2.Address END As Address,
C.phoneNo
From Table3 C, --< Start at common Table3
(Select Rownum r From USER_TABLES Where Rownum < 3) R --< Two rows to replicate Table3 C
-- Any table with more than one row will do
-- USER_TABLES should have enough rows in this particular case
Left Join Table2 B1 On R.r = 1 AND B1.pkId = C.FkId --< Left Join branch one
Left Join table1 A1 On R.r = 1 AND A1.pkId = B1.FkId
Left Join Table5 B2 On R.r = 2 AND B2.pkId = C.FkId --< Left Join branch two
Left Join table4 A2 On R.r = 2 AND A2.pkId = B2.FkId
Where (R.r = 1 AND A1.pkId Is NOT NULL) --/ Make sure we have values
OR (R.r = 2 AND A2.pkId Is NOT NULL) --\ for the branch
But really, consider a view.