Return unique value in SQL when joining two tables - sql

I have question, I have hard time in solving a question on how to actually joining two table using inner join, where the return value shown must only be the unique value on both table.
For example: if table A contains:
ID Name
-------------------
1 Andy
2 Anthony
3 Sandy
And table B:
ID Job
----------------------
1 Student
1 Entrepreneur
3 CEO
It will return only Sandy as CEO and not returning ANDY with both jobs as student and entrepreneur.
Thanks a lot for your time and attention.

A simple join and aggregation would seem to work here:
SELECT a.ID, MAX(a.Name) AS Name, MAX(b.Job) AS Job
FROM TableA a
INNER JOIN TableB b
ON b.ID = a.ID
GROUP BY a.ID
HAVING COUNT(*) = 1;
Demo
The logic here is that the inner join filters off person in the A table not having any match at all in the B table. For those which do have matches, we retain single job match only by checking the count.

Related

SQL JOIN to get the compare two values/row from table "A" and the same row from table "B"

I have two tables with the following rows
Table A (transaction)
Order Seller Customer
1 300 500
Table B (Persons)
PersonID FullName
300 Peter White
500 Scott Bold
I want a result like this
Order Seller Customer FullName (Seller) FullName (customer)
1 300 500 Peter White Scott Bold
I've tried multiple things however which makes more sense is a join a table twice, however I'm getting:
Ambiguous column name
This is SQL Server 2019.
Basically I'm looking to retrieve info from the same table instead of creating additional tables. Is that possible? If yes, how do you do? Thank you in advance.
As #jarlh wrote in comment:
select t.order, t.seller, t.customer, sel.fullname, cust.fullname
from transaction t
join persons sel -- sel is an alias to persons table
on sel.personid = t.seller
join persons cust
on cust.personid = t.customer;
Query with join will return the result as long as both seller and customer exist in persons table -- here it should as source table names transactions :).
I have another form of query it still join table B twice.
This is archaic syntax which I don't recommend but for beginner know the concept of JOIN:
select t.*,B.FullName as FullName (customer) from
(
select A.Order,A.Seller,A.Customer,B.FullName as FullName(Seller)
from A,B where A.Seller=B.PersionID
) t, B where t.Customer=B.PersionID
The proper way of JOIN:
select t.*,B.FullName as FullName (customer) from
(
select A.Order,A.Seller,A.Customer,B.FullName as FullName(Seller)
from A JOIN B ON A.Seller=B.PersionID
) t JOIN B ON t.Customer=B.PersionID
Hoping this can help you.

JOIN query, SQL Server is dropping some rows of my first table

I have two tables customer_details and address_details. I want to display customer details with their corresponding address, so I was using a LEFT JOIN, but when I'm executing this query, SQL Server drops rows where street_no of customer_details table doesn't match with the street_no in address_detials table and displays only rows where `street_no' of customer_detials = street_no of address_details table. I need to display a complete customer_details table and in case if street_no doesn't matches it should display empty string or anything. Am I doing anything wrong in my SQL join?
Table customer_details:
case_id customer_name mob_no street_no
-------------------------------------------------
1 John 242342343 4324234234234
1 Rohan 343233333 43332
1 Ankit 234234233 2342332423433
1 Suresh 234234324 2342342342342
1 Ranjeet 343424323 32233
1 Ramu 234234333 2342342342343
Table address_details:
s_no streen_no address city case_id
------------------------------------------------------
1 4324234234234 Roni road Delhi 1
2 2342332423433 Natan street Lucknow 1
3 2342342342342 Koliko road Herdoi 1
SQL JOIN query:
select
a.*, b.address
from
customer_details a
left join
address_details b on a.street_no = b.street_no
where
b.case_id = 1
Now that it became clear that you used b.case_id=1, I will explain why it filters:
The LEFT JOIN itself returns some rows that contain all NULL values for table b in the result set, which is what you want and expect.
But by using WHERE b.case_id=1, the rows containing NULL values for table b are filtered out because none of them matches the condition (all those rows have b.case_id=NULL so they don't match).
It might work to instead use WHERE a.case_id=1, but we don't know if a.case_id and b.case_id are always the same value for matching rows (they might not be; and if they are always the same, then we just identified a potential redundancy).
There are two ways to fix this for sure.
(1) Move b.case_id = 1 into the left join condition:
left join address_details b on a.street_no = b.street_no and b.case_id = 1
(2) Keep b.case_id = 1 in the WHERE but also allow for NULLED-out b values:
left join address_details b on a.street_no = b.street_no
where b.case_id = 1
or b.street_no IS NULL
Personally I'd go for (1) because that is the most clear way to express that you want to filter b on two conditions, without affecting the rows of a that are being returned.
I do think that Wilhelm Poggenpohl answer is kind of right. You just need to change the last join condition a.case_id=1 to b.case_id=1
select a.* , b.address
from customer_details a
left join address_details b on a.street_no=b.street_no
and b.case_id=1
This query will show every row from customer_details and the corresponding adress if there is a match of street_no and the adress meets the condition case_id=1.
This is because of the where clause. Try this:
select a.* , b.address
from customer_details a
left join address_details b on a.street_no=b.street_no
and a.case_id=1

How to get the unmatched records from two tables using Joins

I have two tables one is teacher and another is Department which is mentioned below.
Teacher Table
Id Name
1 xyz
2. Gjd
3. Dftr
4 dhdk
Department Table
Id Name EMPID
1 SQL. 2
2. PHP. 4
3. JAVA. 1
4 PEARL. 5
QUESTION
i want those records of teacher which are not link with any Department.
you can use following statement using left join then filter Teacher that not matched
SELECT t.*
FROM Teacher t
left join Department d on d.EMPID = t.Id
where d.id is null
SELECT * FROM teachers WHERE
id NOT IN (SELECT DISTINCT EMPID FROM departments) ;
Hope this helps.!!
you can do it by inner query..
select * from teacher where id not in (select empid from department);

SQL: Unable to find a join or union to produce the following table

A Pupil table with { ID, LastName}
a Subject Table with {ID, SubjectName}
and a Report Table with {ID, PupilID, SubjectID, Grade}
There is a one-to-many relationship between Pupil and Report Tables, and Subject and Report Tables.
I want to generate a table like this for say subjectID = 1
Pupil.ID Pupil.LastName SubjectID Grade
1 --------------Smith ---------- 1 ------------B
2 --------------Jones ---------- 1 ------------NULL
3 -------------Weston ----------1 ------------NULL
4 -------------Knightly ---------1 -----------A
The problem is that the Report table would contain just 2 entries for subject 1:
PupilID SubjectID Grade
----1------- 1 ----------- B
----4------- 1 ----------- A
Left joins don't seem to work since there are only 2 entries in the report table for subject 1
SAMPLE DATA
{Pupil Table}
ID LastName
1 ...Smith
2 ...Jones
3 ...Weston
4 ...Knightly
{Subject Table}
ID SubjectName
1 ....Maths
2 ....Physics
3 ....Chemistry
{Report Table}
ID PupilID SubjectID Grade
1 .......1 ..........1 ..........B
2 .......4 ..........1 ..........A
When I do a search on SubjectID = 1 I want the table:
Pupil.ID .......Pupil.LastName ........SubjectID ...........Grade
1 --------------Smith ---------- 1 ------------B
2 --------------Jones ---------- 1 ------------NULL
3 -------------Weston ----------1 ------------NULL
4 -------------Knightly ---------1 -----------A
Access doesn't do subqueries very easily, so everything gets crammed into the FROM clause with a series of wrapped parentheses. Based on your sample data and my fighting Access to stop being unnecessarily difficult, I came up with this:
SELECT ps.Pupil_ID, ps.LastName, ps.Subject_ID, r.Grade
FROM (SELECT * FROM (SELECT ID AS Pupil_ID, LastName FROM Pupil) p,
(SELECT DISTINCT ID AS Subject_ID FROM Subject)) ps
LEFT JOIN REPORT r ON r.PupilID = ps.Pupil_ID AND r.SubjectID = ps.Subject_ID
ORDER BY Pupil_ID, Subject_ID;
The subquery "ps" is a cartesian join of the Pupil and Subject table views that I specified. At this point, your query would look like this:
(LastName column not shown for clarity)
StudentID|SubjectID
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Now, using that Cartesian join subquery (pupilstudent -> ps), I use a LEFT JOIN to assign the Report table to each unique student's ID and subject ID. Therefore, if a student did not take a particular class, there will be a NULL value in the final result.
I tested this in Access using your sample data and it works on my machine.
Also as a note, it is poor practice to have a field called just ID in each table (e.g. in the Pupil table, ID becomes PupilID). This makes it much easier to use, and it self documents.
Cross join pupil and subject tables and left join result to report table
What you need is a cross join:
SELECT Pupil.ID, Pupil.LastName, SubjectID, Grade FROM
Pupil, Subject LEFT JOIN Report ON Subject.ID=Report.SubjectID
WHERE Subject.ID=1
To combine every pupil with every (or with a particular) subject, use cross join; Then use left join to get the corresponding grades:
select *
from pupil p cross join (select * from subject where id = 1) s
left join report on subjectId = s.id and pupilId = p.id

SQL Inner join in a nested select statement

I'm trying to do an inner join in a nested select statement. Basically, There are first and last reason IDs that produce a certain number (EX: 200). In another table, there are definitions for the IDs. I'm trying to pull the Last ID, along with the corresponding comment for whatever is pulled (EX: 200 - Patient Cancelled), then the first ID and the comment for whatever ID it is.
This is what I have so far:
Select BUSN_ID
AREA_NAME
DATE
AREA_STATUS
(Select B.REASON_ID
A.LAST_REASON_ID
FROM BUSN_INFO A, BUSN_REASONS B
WHERE A.LAST_REASON _ID=B.REASON_ID,
(Select B.REASON_ID
A. FIRST_REASON_ID
FROM BUSN_INFO A, BUSN_REASONS B
WHERE A_FIRST_REASON_ID = B.REASON_ID)
FROM BUSN_INFO
I believe an inner join is best, but I'm stuck on how it would actually work.
Required result would look like (this is example dummy data):
First ID -- Busn Reason -- Last ID -- Busn Reason
1 Patient Sick 2 Patient Cancelled
2 Patient Cancelled 2 Patient Cancelled
3 Patient No Show 1 Patient Sick
Justin_Cave's SECOND example is the way I used to solve this problem.
If you want to use inline select statements, your inline select has to select a single column and should just join back to the table that is the basis of your query. In the query you posted, you're selecting the same numeric identifier multiple times. My guess is that you really want to query a string column from the lookup table-- I'll assume that the column is called reason_description
Select BUSN_ID,
AREA_NAME,
DATE,
AREA_STATUS,
a.last_reason_id,
(Select B.REASON_description
FROM BUSN_REASONS B
WHERE A.LAST_REASON_ID=B.REASON_ID),
a.first_reason_id,
(Select B.REASON_description
FROM BUSN_REASONS B
WHERE A.FIRST_REASON_ID = B.REASON_ID)
FROM BUSN_INFO A
More conventionally, though, you'd just join to the busn_reasons table twice
SELECT i.busn_id,
i.area_name,
i.date,
i.area_status,
i.last_reason_id,
last_reason.reason_description,
i.first_reason_id,
first_reason.reason_description
FROM busn_info i
JOIN busn_reason first_reason
ON( i.first_reason_id = first_reason.reason_id )
JOIN busn_reason last_reason
ON( i.last_reason_id = last_reason.reason_id )