Inner Join on Empty Values - sql-server

TableName:Emp
EmpId EmpName EmpAddressId
1 Ram 100
2 Ravi
3 Raj 102
4 Kiran
5 Bujji 101
TableName:Address
AddressId Address
101 India
102 Uk
103 US
select E.*,A.Address from EMP E inner join Address A
on E.EmpId=2 and E.EmpAddressId='' or E.EmpAddressId=A.AddressId
out put should display as for EmpId:2
------------------------------
EmpId EmpName EmpAddressId Address
2 Ravi
for EmpId:3
------------
EmpId EmpName EmpAddressId Address
3 Raj 102 Uk
For employee 2 there is no EmpAddressId but here requirement is need to display as null values or empty values.
can any one help this.

Just replace INNER JOIN with a LEFT JOIN (or LEFT OUTER JOIN). That will result in NULL for all columns from Address table if there's no match. Also, you can replace your join condition with a simpler version:
select E.EmpId, E.EmpName, E.EmpAddressId, A.Address
from EMP E left join Address A
on E.EmpAddressId=A.AddressId
where E.EmpId=2
More on outer joins on MSDN.

Inner join will yield to null if any of the joining table is null.. If all the table has value then use inner join else go for left join. It ensures that atleast you will get let joined table values.
For this ,you use left join
select e.EmpId, e.EmpName, e.EmpAddressId, a.Address
from EMP e left join Address a
on e.EmpAddressId=a.AddressId
where e.EmpId=2

Related

T-SQL query to get desired output

I have 2 below tables called T1 and T2
T1 having data as follows
DateList
2021-11-06
2021-11-07
2021-11-08
2021-11-09
T2 having data as follows
EmpId ApplyDate
1 2021-11-07
1 2021-11-09
2 2021-11-09
Now i need t-sql statement that will give date which is not there in T2 for each EmpId.
Output should look as below
DateList EmpId
2021-11-06 1
2021-11-08 1
2021-11-06 2
2021-11-07 2
2021-11-08 2
We can use a cross join between the two tables to generate a reference table containing all date/employee pairs. Then, left anti-join this table to T2 to find all pairs which are not present.
SELECT d.DateList, e.EmpId
FROM T1 d
CROSS JOIN (SELECT DISTINCT EmpId FROM T2) e
LEFT JOIN T2
ON T2.DateList = d.DateList AND
T2.EmpId = e.EmpId
WHERE
T2.DateList IS NULL
ORDER BY
d.DateList,
e.EmpId;

Data merge in SQL

I tried the below query to display data
select e.Name,ic.Code,t1.pyear,t1.pmonth,t2.Amount
from t1
inner join t2 on t2.id=t1.id
inner join t3 on t3.Code=t2.Code
inner join t4 e on t4.employeeindex=t1.employeeindex
where t1.pyear=2016 and t1.pmonth=1
union all
select e.Name,ic.Code,t1.pyear,t1.pmonth,t2.Amount
from t1
inner join t2 on t2.id=t1.id
inner join t3 on t3.Code=t2.Code
inner join t4 e on t4.employeeindex=t1.employeeindex
where t1.pyear=2016 and t1.pmonth=2
and the data i am getting is like this-
scode amount month year e_name
abc 3847 1 2016 john
ABC 20938 2 2016 john
XYZ 2838 1 2016 david
XYZ 29384 2 2016 david
now i want to display data like this
s_code amount1 amount2 month1 month2 year e_name
abc 3847 20938 1 2 2016 john
xyz 2838 29384 1 2 2016 david
any solution ?
edit
You could try to use cte. The following is just an example, adjust the column names by yourself because it's a bit of a mess
WITH unionall AS (
select ic.Code, t2.Amount, t1.pmonth, t1.pyear, e.Name
from t1
inner join t2 on t2.id=t1.id
inner join t3 on t3.Code=t2.Code
inner join t4 e on t4.employeeindex=t1.employeeindex
where t1.pyear=2016 and (t1.pmonth=1 OR t2.pmonth=2)
)
SELECT r1.scode, r1.amount as amount1, r2.amount as amount2
FROM unionall r1 inner join unionall r2 on r1.scode = r2.scode
-----------------------
If you know for sure that for each s_code there are 2 months (or at least a costant number) you could easily make a join on itself and select all the values with an alias, like so:
SELECT r1.scode, r1.amount as amount1, r2.amount as amount2 [...more fields...]
FROM result r1 inner join result r2 on r1.scode = r2.scode [...many joins as many months...]
If there can be multiple month that you don't know, i would probably do what on mysql is a group_concat. Basically, you group by scode and then, in the same field, there's a list separated values. Too bad you can't do a group_concat in SQLServer, but there are workaround guides around the web
How to make a query with group_concat in sql server

SQL Server join two columns both ID of a table with another table's primary Key Column

I was wondering if there is an easy way of joining these two tables.
Table1
Name FromCountryID ToCountryID
------------------------------
sam 1 2
lee 3 4
john 2 1
Table2:
CountryID CountryName
1 USA
2 UK
3 Canada
4 Nepal
You need to join the same table twice with different alias names
select t1.name,
fromTab.countryName as FromCountry,
toTab.countryName as ToCountry
from table1 t1
left join table2 fromTab on fromTab.countryId = t1.fromCountryId
left join table2 toTab on toTab.countryId = t1.toCountryId
SELECT * FROM Table1 INNER JOIN Table2 ON Table2.CountryID = Table1.FromCountryID

Filter out some records on particular periods

I have below tables structures,
Trans Table:
Trans_Id(PK) User_Id(FK) Arroved_Date
________________________________________________
1 101 05-06-2016
2 101 20-06-2016
3 102 06-06-2016
4 103 10-06-2016
5 103 25-06-2016
Table2:
Id(Pk) User_Id(Fk) Start_Date End_Date
__________________________________________________________________
1 101 01-06-2016 15-06-2016
2 103 05-06-2016 20-06-2016
I want to filter out the transaction, if the Approved_Date is not between the users Start_Date and End_Date of table2.
Expected Result:
Trans_Id
________
2
3
5
This query should give you the expected results:
select t1.trans_id from t1
left join t2
on t1.user_id=t2.user_id
where t2.id is null OR t1.Arroved_Date not between t2.Start_Date and t2.End_Date
Try
SELECT Trans_ID
FROM Table1
JOIN Table2 ON Table1.User_Id=Table2.User_Id
where Approved_date Between Start_Date And End_Date
i'm not sure but from you expected output..
SELECT distinct t1.Trans_ID
FROM Table1 t1
LEFT JOIN Table2 t2 on 1=1
where t1.Approved_date Between t2.Start_Date And t2.End_Date
Based on your explanation (not on the expected result) you need to just JOIN the two tables on the FK you pointed out, in order to get the relationship between the rows in the two tables.
Then just apply a WHERE clause to filter the row based on your condition:
select t.trans_id
from trans t
inner join table2 t2 on t.user_id = t2.user_id
where t.approved_date between t2.start_date and t2.end_date
SELECT t.trans_id
FROM Trans tr
LEFT JOIN Table2 t2 ON tr.User_id = t2.User_id
WHERE t2.id IS NULL
OR t.Approved_Date IS NULL
OR t2.Start_Date IS NULL
OR t2.End_Date IS NULL
OR tr.Approved_Date <= t2.Start_Date
OR tr.Approved_Date >= t2.End_Date
The null-checks are only needed if the columns are nullable. The left join can be changed to an inner join if every transaction has a corresponding row in table 2. The answer assumes that there is not more than one row in table 2 for each transaction.
Try this one.
SELECT A.Trans_ID
FROM TEMP A
JOIN TEMP B ON A.User_Id = B.User_Id
WHERE A.Approved_date BETWEEN Start_Date AND End_Date

query to return null values when none exist in one table

I need to list out 6 medical offices in one column, and the patient's full name in the other. If the patient has never visited that office before, then a NULL should appear.
The table structures are simple with MedicalOffice having an ID,
Name, and a few miscellaneous columns.
MedicalProcedure has the
officeID, patientID, patient's full name, and some miscellaneous
columns.
There is only one ID per office in the MedicalOffice table, but MedicalProcedure can have many officeIDs per patient and even the same officeID for the same patient more than once.
Following some answers I found here on SO, I tried a left outer join:
select m.Name, p.FullName
from MedicalOffice m
left outer join MedicalProcedure p ON m.ID = p.officeID
where m.ID IN (1,2,3,4,5,6)
AND p.patientID = 111
GROUP BY m.Name, p.patientID
ORDER BY m.Name
Then a left join:
select m.Name, p.FullName
from MedicalOffice m
left join MedicalProcedure p ON m.ID = p.officeID
where m.ID IN (1,2,3,4,5,6)
AND p.patientID = 111
GROUP BY m.Name, p.patientID
ORDER BY m.Name
but I only get the offices where a record exists in the MedicalProcedure table like this:
Name | FullName
----------------------------------
Office 1 Smith, John
Office 2 Smith, John
Office 4 Smith, John
But, if patientID 111 had 3 records in the MedicalProcedure table for Offices 1,2, and 4, the results should look like this:
Name | FullName
----------------------------------
Office 1 Smith, John
Office 2 Smith, John
Office 3 NULL
Office 4 Smith, John
Office 5 NULL
Office 6 NULL
Is there a way to get the results I need?
Thanks!
Just move p.patientID = 111 condition into ON clause. In Where it effectively changes outer join into inner join:
Select
Distinct --< Substitute for Group By
m.Name, p.FullName
From MedicalOffice m
Left Join MedicalProcedure p On m.ID = p.officeID AND p.patientID = 111
Where m.ID IN (1,2,3,4,5,6)
/* Group By m.Name, p.patientID */ --< won't work in this example
Order By m.Name
Remove
m.ID IN (1,2,3,4,5,6)
This condition will stop null value showup

Resources