tsql join tables with 2 ids - sql

I have this tables (Users and Meetings):
UserId | Name
1 | John
2 | Linda
3 | David
and
UserId_1 | UserId_2 | MeetingDate
1 | 2 | 15/01/2018
3 | 2 | 17/01/2018
1 | 3 | 19/01/2018
How do I select from the 2 tables in order to get in each row the Name associated to each id? I'd like to get something like this:
UserId_1 | UserId_2 | User_1_Name | User_2_Name | MeetingDate
1 | 2 | John | Linda | 15/01/2018
3 | 2 | David | Linda | 17/01/2018
1 | 3 | John | David | 19/01/2018
Thank you.

You just need two inner join:
SELECT m.UserId_1
,m.UserId_2
,u1.NAME
,u2.NAME
,m.MeetingDate
FROM Meetings m
INNER JOIN Users u1 ON u1.UserId = m.UserId_1
INNER JOIN Users u2 ON u2.UserId = m.UserId_2

You just need to alias one or both references to the table which you need to join twice...
SELECT
user1.UserId AS UserId_1,
user2.UserId AS UserId_2,
user1.Name AS User_1_Name,
user2.Name AS User_2_Name,
Meetings.MeetingDate
FROM
Meetings
INNER JOIN
Users AS user1
ON user1.UserId = Meetings.UserId_1
INNER JOIN
Users AS user2
ON user2.UserId = Meetings.UserId_2
The alias means that you can reference which instance of Users you're referring to without any ambiguity.

select Meetings.UserId_1,
Meetings.UserId_2,
isnull(a.Name,'--Unknown--') User_1_Name,
isnull(b.Name,'--Unknown--') User_2_Name,
MeetingDate
from Meetings left join Users a on Meetings.UserId_1 = a.UserID
left join Users b on Meetings.UserId_2 = b.UserID

Another approach is
SELECT m.UserId_1
,m.UserId_2
,(select name from Users where Users.id = m.UserId_1) as User_1_Name
,(select name from Users where Users.id = m.UserId_2) as User_2_Name
,m.MeetingDate
FROM Meetings m
Regards
Abdul

Related

JOIN the table if records exist

is it possible if i want to do INNER JOIN only if the record exist on the 2nd table if not then dont join?
this is my table
User table
+--------+--------------+
| id | name |
+--------+--------------+
| 1 | John |
+--------+--------------+
| 2 | Josh |
+--------+--------------+
House table
+--------+-------------+--------------+
| id | owner_id | house_no |
+--------+-------------+--------------+
| 1 | 1 | 991 |
+--------+-------------+--------------+
this is my INNER JOIN query
SELECT h.owner_id, u.name, h.house_no FROM user u
INNER JOIN house h on u.id = h.owner_id
WHERE u.id = :id
it will return this result if id = 1
+--------+--------------+--------------+
| id | name | house_no |
+--------+--------------+--------------+
| 1 | John | 991 |
+--------+--------------+--------------+
but if i run with id = 2 no result returned.
what i want to do right now is it still return the result even when no data exist for id = 2 in table house
Use a left outer join instead.
SELECT u.id, u.name, h.house_no FROM user u
LEFT OUTER JOIN house h on u.id = h.owner_id
WHERE u.id = :id
The resulting record will be:
+--------+--------------+--------------+
| id | name | house_no |
+--------+--------------+--------------+
| 2 | Josh | null |
+--------+--------------+--------------+

PostgreSQL join two tables with LIMIT 1

I have two tables:
First table "persons"
id | name |
---------------
1 | peter |
3 | martin |
5 | lucy |
Second table "meetings"
id | date | id_persons |
--------------------------------
1 | 2014-12-08 | 1 |
2 | 2013-05-10 | 2 |
3 | 2015-08-25 | 1 |
4 | 2016-10-18 | 1 |
5 | 2012-01-01 | 3 |
6 | 2016-09-28 | 5 |
I need somehow get only last date from "meeting" table for every person (or selected). And result table must be order by name. I thought, it could be like this, but WHERE clause in LEFT JOIN can't be used:
SELECT meetings.id, meetings.date, persons.name FROM persons
LEFT JOIN (SELECT meetings.date, meetings.id, meetings.id_persons FROM
meetings WHERE persons.id = meetings.id_persons ORDER BY
meetings.date DESC LIMIT 1) m ON m.id_persons = persons.id
WHERE persons.id < 6 ORDER BY persons.name
So I started with DISTINCT and it worked, but I think that it is not good idea:
SELECT * FROM
(SELECT DISTINCT ON (persons.id) persons.id, persons.name,
m.date, m.id FROM persons
LEFT JOIN (SELECT meetings.id, meetings.date, meetings.id_persons
FROM meetings ORDER BY meetings.date DESC) m
ON m.id_persons = persons.id
WHERE persons.id < 6 ORDER BY persons.id) p
ORDER BY p.name
Result what I need is:
name | date | id_meetings
-----------------------------------
lucy | 2016-09-28 | 6
martin | 2012-01-01 | 5
peter | 2016-10-18 | 4
Could you help me with better solution?
In Postgres, the easiest way is probably distinct on:
select distinct on (p.id) p.*, m.*
from persons p left join
meetings m
on m.id_persons = p.id
order by p.id, m.date desc;
Note: distinct on is specific to Postgres.

Inner queries on the same table - is there a better way?

I have these two tables (simplified versions)
Orders
owner_id | user_1 | user_2 | amount | order_id
-----------------------------------------------
1 | 2 | 3 | 100 | AAA
1 | 7 | 2 | 200 | BBB
2 | 3 | 5 | 400 | CCC
Users
user_id | username
------------------
1 | John
2 | Robert
3 | Sally
4 | Mario
5 | Albert
6 | Hernest
7 | Homer
I need to get, in one query, all the info related to a particular order, including the owner_id, user_1, user_2 usernames.
The result I'm trying to achieve is the following:
owner_id | owner_username | user_1_id | user_1_username | user_2_id | user_2_username | order_total
----------------------------------------------------------------------------------------------------
1 | John | 2 | Robert | 3 | Sally | 100
So far I'm getting all I need with a query like this:
SELECT o.owner_id AS owner_id, (SELECT username FROM Users where user_id = 1) AS owner_username,
o.user_1 AS user_1_id, (SELECT username FROM Users where user_id = 2) AS user_1_username,
o.user_2 AS user_2_id, (SELECT username FROM Users where user_id = 3) AS user_2_username,
o.amount AS order_total
FROM Orders.o
WHERE o.order_id = 'AAA'
This is an example to retrieve the info for the first order.
I'm not very satisfied by the inner queries I have to do to get each username, I think it's kinda ugly.
Is there a more elegant or more performant way to get the usernames?
Thank you
This may help
SELECT od.*,
U1.username AS 'User_1_Name',
U2.username AS 'User_2_Name',
U3.username AS 'User_3_Name'
FROM Orders od
LEFT OUTER JOIN Users U1
ON od.Owner_Id = U1.User_Id
LEFT OUTER JOIN Users U2
ON od.User_1 = U2.User_Id
LEFT OUTER JOIN Users U3
ON od.User_2 = U3.User_Id
WHERE order_id = 'AAA'

sql query joining two columns with one

I have 2 tables in ms access 2010 as below
USERS (u_id, u_name)
LOAN (l_id, l_from[ref users.u_id], l_to[ref users.u_id], l_amount)
Users
+------+--------+
| u_id | u_name |
+------+--------+
| 1 | abc |
| 2 | def |
+------+--------+
Loan
+-----+--------+------+----------+
|l_id | l_from | l_to | l_amount |
+-----+--------+------+----------+
| 1 | 2 | 1 | 100 |
| 2 | 2 | 1 | 100 |
| 3 | 1 | 1 | 50 |
+-----+--------+------+----------+
I want to select names instead of numbers(l_from & l_to) from loan table
select
loan.l_id,
loan.l_from,
users.u_name user_from,
loan.l_to,
users.u_name as user_to,
loan.l_amount
from loan, users
where ???
JOIN the users table two times like so:
SELECT
l.l_id,
fromusers.u_name AS user_from,
tousers.u_name AS user_to,
l.l_amount
FROM loan l
INNER JOIN users fromusers ON l.l_from = fromusers.u_id
INNER JOIN users tousers ON l.l_to = tousers.u_id
SQL Fiddle Demo (it is SQL Server 2008, but should be the same syntax for ms-access, I think)
Just join on the Users table twice, once for each of from and to.
SELECT l.l_id, uFrom.u_name AS user_from,
uTo.u_name AS user_to, l.l_amount
FROM LOAN l
INNER JOIN Users uFrom ON l.l_from = uFrom.u_id
INNER JOIN Users uTo ON l.l_to = uTo.u_id

SQL - Inner join on two columns from table 1 with one column from table 2?

I have a table that has two columns that each contain a member id that is a foreign key to a members table that contains their name. I want to select the first table with names instead of member IDs. I'm not sure of a way to do this. I feel like there's certainly a way involving an INNER JOIN, but I can't think of how to pick two names from one table in one INNER JOIN. Any ideas?
Thanks in advance!
Match table
|------|-------|
| user | match |
|------|-------|
| 1 | 4 |
| 2 | 1 |
| 3 | 2 |
|------|-------|
Members table
|------|-------|
| user | name |
|------|-------|
| 1 | Joe |
| 2 | Kyle |
| 3 | John |
| 4 | Nate |
|------|-------|
Desired output
|------|-------|
| user | match |
|------|-------|
| Joe | Nate |
| Kyle | Joe |
| John | Kyle |
|------|-------|
You should join members table for twice.
SELECT M1.NAME , M2.NAME
FROM MEMBERS M1
INNER JOIN MATCH M
ON M1.USER = M.USER
INNER JOIN MEMBERS M2
ON M2.USER = M.MATCH
Be carefull with lower and upper identifiers if your database is mysql.
You can also do this with an Outer Apply: http://sqlfiddle.com/#!3/8f932/5
SELECT me.name as 'User',
mem.name as 'Match'
FROM Match m
OUTER APPLY(
SELECT me.name
FROM Members me
WHERE me.id = m.match
)mem
LEFT JOIN Members me on me.id = m.id
Or: http://sqlfiddle.com/#!3/8f932/6
SELECT me.name as 'User',
mem.name as 'Match'
FROM Match m
LEFT JOIN Members mem on mem.id = m.match
LEFT JOIN Members me on me.id = m.id
You can do two joins:
SELECT u1.name, u2.name
FROM members u1
INNER JOIN match m
ON u1.user = m.user
INNER JOIN members u2
ON u2.user = m.match