Create a additional row from join sql? - sql

I have 2 tables: Person and House with 1-n relation.
I want to the result return as picture below:
Row always have a Person column with a null House column.
Thanks.

you can use unionall to join the result set with person table something like
select p.name,h.name as housename from person p join house h on p.id=h.personid
union all (select name,null from person)
order by name,housename

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.

joining a table on 2 fields

I want to pull a person and their supervisor names from a table. The persons table has the supervisor_id and the person_id. The names table has name_id and a Full Name field. If I join Person ON either supervisor_id or person_id, how do I get the other to display as well?
You need to join twice, one for each relationship you have:
SELECT
-- Persons' columns
P.*,
-- Superviser name columns
SN.*,
-- Person name columns
PN.*
FROM
persons AS P
LEFT JOIN names AS SN ON P.supervisor_id = SN.name_id
LEFT JOIN names AS PN ON P.person_id = PN.name_id
Or you can join with an OR clause, but you won't be able to know which record did you join with unless you check with a CASE.
SELECT
-- Persons' columns
P.*,
-- name columns
N.*,
IsSupervisor = CASE WHEN P.supervisor_id = N.name_id THEN 'Yes' ELSE 'No' END
FROM
persons AS P
LEFT JOIN names AS N ON
P.supervisor_id = N.name_id OR
P.person_id = N.name_id
This last approach will display 2 rows as it will match either one or the other on different occasions, not both with the same persons row (as the first example).
A (self)join is what you need:
select p.*, supervisor=ps.name
from Person p join person ps on p.supervisor_id=ps.id

Condition for finding rows with same value in one colum and null in another column

I have a table with columns student ID, subject, Enrolled. I have a row for each subject against a student. I am inserting this data to a temp table for reporting. I have another column named reporting in this temp table. I need to update reporting false when enrolled is null for all the rows imported for a student.
Here is the approach:
Select from all students
Left outer join to student-course (outer join is important here)
Group by student ID, and get min course ID
Use rows with null course ID to decide what temp rows to update
In SQL this query would look like this:
SELECT StudentId, MIN(CourseId)
FROM Student s
LEFT OUTER JOIN StudentCourse sc
ON s.StudentId=sc.StudentId
GROUP BY s.StudentId
HAVING MIN(CourseId) IS NULL

Update multiple row values to same row and different columns

I was trying to update table columns from another table.
In person table, there can be multiple contact persons with same inst_id.
I have a firm table, which will have latest 2 contact details from person table.
I am expecting the firm tables as below:
If there is only one contact person, update person1 and email1. If there are 2, update both. If there is 3, discard the 3rd one.
Can someone help me on this?
This should work:
;with cte (rn, id, inst_id, person_name, email) as (
select row_number() over (partition by inst_id order by id) rn, *
from person
)
update f
set
person1 = cte1.person_name,
email1 = cte1.email,
person2 = cte2.person_name,
email2 = cte2.email
from firm f
left join cte cte1 on f.inst_id = cte1.inst_id and cte1.rn = 1
left join cte cte2 on f.inst_id = cte2.inst_id and cte2.rn = 2
The common table expression (cte) used as a source for the update numbers rows in the person table, partitioned by inst_id, and then the update joins the cte twice (for top 1 and top 2).
Sample SQL Fiddle
I think you don't have to bother yourself with this update, if you rethink your database structure. One great advantage of relational databases is, that you don't need to store the same data several times in several tables, but have one single table for one kind of data (like the person's table in your case) and then reference it (by relationships or foreign keys for example).
So what does this mean for your example? I suggest, to create a institution's table where you insert two attributes like contactperson1 and contactperson2: but dont't insert all the contact details (like email and name), just the primary key of the person and make it a foreign key.
So you got a table 'Person', that should look something like this:
ID INSTITUTION_ID NAME EMAIL
1 100 abc abc#inst.com
2 101 efg efg#xym.com
3 101 ijk ijk#fg.com
4 101 rtw rtw#rtw.com
...
And a table "Institution" like:
ID CONTACTPERSON1 CONTACTPERSON2
100 1 NULL
101 2 3
...
If you now want to change the email adress, just update the person's table. You don't need to update the firm's table.
And how do you get your desired "table" with the two contact persons' details? Just make a query:
SELECT i.id, p1.name, p1.email, p2.name, p2.email
FROM institution i LEFT OUTER JOIN person p1 ON (i.contactperson1 = p1.id)
LEFT OUTER JOIN person p2 ON (i.contactperson2 = p2.id)
If you need this query often and access it like a "table" just store it as a view.

Joining same table multiple times

I have 2 tables Person an Department - where each person has multiple departments registered against him.
Person
id|name|dept1|dept2|dept3
1 |Jane|100 |102 |106
Dept
id |Name
100|Accounts
...
102|HR
...
106|Admin
Whats the most elegant sql to display Jane's record as follows:
Jane|Accounts|HR|Admin
Use this. And work on your naming convention to make all column names unique independent of table.
SELECT
Person.id, Person.name, dept1.Name, dept2.Name, dept3.Name
LEFT JOIN Dept dept1 ON dept1.id = Person.dept1
LEFT JOIN Dept dept2 ON dept2.id = Person.dept2
LEFT JOIN Dept dept3 ON dept3.id = Person.dept3
Something like this will let you join the same table multiple times. You just give each join a different alias
SELECT *
FROM Person AS P
INNER JOIN Dept AS D1 ON P.dept1 = D1.id
INNER JOIN Dept AS D2 ON P.dept2 = D2.id
WHERE P.name = 'Jane'
Ideally you would normalise the data in your Person table and have a linking table between Person and Dept e.g. PersonDepartmentLinking (or whatever convention you have for linking table naming conventions), assuming you have any control over the schema and it's possible to add the relationship that way.
You can use STUFF in this case
Select name,
Stuff((Select distinct ', ' + cast(Name as varchar(20))
From #Dept t2
Where t2.Id = t1.Id
FOR XML PATH('')),1,1,'')
From Person t1
The only way that I know is a join for each column.
But if you are in the way of designing the tables, i suggest you to normalize the DB.
If a person need an extra dept column, you need to alter the table to add a new property of person.
For me, 3 entities are needed:
- Person
- Department
- person_department_assignation