display basic information from tables - sql

I have two tables i.e.
Users
uid | firstname
1 | John
2 | Bob
3 | Paul
4 | Peter
Calls
cid | assigned_to | caller_id
1 | 2 | 1
2 | 1 | 3
3 | 2 | 4
4 | 4 | 2
assigned_to and caller_id are just the uid in users.
I just want to display the results of each call:
call_id | username(assigned_to) | username(caller_id)
How can I do this in SQL?
Thanks,

Try this:
select
cid as call_id,
A.username, -- assingned to
B.username -- caller id
from calls
left join users A on calls.assigned_to = A.uid
left join users B on calls.caller_id = B.uid

Related

Iterating multiple times over same table (postgres sql)

i am working with sql from few days as beginner and stuck at a problem!
Problem:
Given A table user_email_table which columns are (id, user_id, user_id_email)
How to get all user co-related to each and every user extending himself
user_email_table
id | user_id | email_id
1 | 1 | xyz
2 | 2 | xyz2
3 | 3 | xyz3
4 | 4 | xyz4
Desired Output
id | user_id_1 | user_id_2 | user_id_1_email | user_id_2_email |
-----------------------------
1 | 1 | 2 | xyz|xyz2|
1 | 1 | 3 |xyz|xyz3|
1 | 1 | 4 |xyz|xyz4|
1 | 2 | 1 |xyz2|xyz1|
1 | 2 | 3 |xyz2|xyz3|
1 | 2 | 4 |xyz2|xyz4|
1 | 3 | 1 |xyz3|xyz1|
1 | 3 | 2 |xyz3|xyz2|
1 | 3 | 4 |xyz3|xyz4|
1 | 4 | 1 |xy4|xyz1|
1 | 4 | 2 |xyz4|xyz2|
1 | 4 | 3 |xyz4|xyz3|
Please Ignore validate data of email fields This are just for reminding to mention these columns in output-table
What SQL query can result into this table
You want a "cross join" of the table against itself excluding the self-matching rows. You can do:
select
1 as id,
a.user_id as user_id_1,
b.user_id as user_id_2,
a.email_id as user_id_1_email,
b.email_id as user_id_2_email
from user_email_table a
cross join user_email_table b
where a.user_id <> b.user_id
EDIT:
As #IMSoP points out the query can also use a common join with a join predicate and can be rephrased as:
select
1 as id,
a.user_id as user_id_1,
b.user_id as user_id_2,
a.email_id as user_id_1_email,
b.email_id as user_id_2_email
from user_email_table a
join user_email_table b on a.user_id <> b.user_id

Postgres SQL query to get the first row of distinct id

channels table
id | name
------------
1 | ABC
2 | XYZ
3 | MNO
4 | ASD
user_channels table
user_id | channel_id
----------------------
555 | 1
666 | 1
777 | 1
555 | 2
888 | 2
999 | 3
555 | 3
user_chats table
id | created_at | channel_id | content
---------------------------------------
2 | time 1 | 1 | Hello
3 | time 2 | 1 | Hi
4 | time 3 | 2 | Good day
5 | time 4 | 2 | Morning
I have these 3 tables in postgres SQL,
I want to write a sql query to get user_channels by user_id and it's latest message only (time 1 is oldest message) from user_chats table. How can I do that?
For example, for user_id = 555, the query should return
channel_id | content | created_at
---------------------------------------
1 | Hi | time 2
2 | Morning | time 4
3 | Null | Null
Use distinct on:
select distinct on (a.channel_id) a.*
from user_chats a
inner join user_channels l on l.channel_id = a.channel_id
where l.user_id = 555
order by a.channel_id, a.createt_at desc
If you want this for all users at once:
select distinct on (l.user_id, a.channel_id) l.user_id, a.*
from user_chats a
inner join user_channels l on l.channel_id = a.channel_id
order by l.user_id, a.channel_id, a.createt_at desc
You can use distinct on:
select distinct on (c.channel_id) c.channel_id, uc.content, uc.created_at
from user_channels c left join
user_chats uc
on uc.channel_id = c.channel_id
where c.user_id = ?
order by c.idchannel_id, uc.created_at desc;

SQL check if a record has a reference from another table and if so do something

I have two tables, users and friendships
id | name | password
-------------------------
1 | Dave | 1234
-------------------------
2 | John | abcd
-------------------------
3 | Bob | xyz
-------------------------
and the friendships
friend_one | friend_two | status
-------------------------------------
1 | 1 | me
-------------------------------------
2 | 2 | me
-------------------------------------
3 | 3 | me
------------------------------------
1 | 2 | pending
-------------------------------------
3 | 1 | active
Now whenever a user logged in to the system, I need to fetch all the users in the database, also I need to add an extra column to the result from the select query, which shows the friendship status with currently logged in user.
For example, user id 1 , Dave logged in to the system and request for users list, select query should be output as below,
id | name | password | friend_status
------------------------------------------
1 | Dave | 1234 | me
------------------------------------------
2 | John | abcd | pending
------------------------------------------
3 | Bob | xyz | active
------------------------------------------
When the user id 2, John logged in to the system, he need to get the below table,
id | name | password | friend_status
------------------------------------------
1 | Dave | 1234 | pending
------------------------------------------
2 | John | abcd | me
------------------------------------------
3 | Bob | xyz | null
------------------------------------------
Is this even possible ? I tried to join tables and use a nested query
For example, with the below query I can get all the friendships for the currently logged in user,
select * from friendships
where friend_one = 2 or friend_two = 2
But I don't understand what to do next. I tried to put this as a nested query of the main select query and tried to join tables but I'm not getting what I wanted.
Can anyone give me an idea?
You need to CROSS JOIN the list of id values from users with the users table to get all distinct pairs of id values, then LEFT JOIN that to the friendships table to get the friend status for each user:
SELECT u1.id, u.name, u.password,
f.status
FROM users u
CROSS JOIN (SELECT DISTINCT id
FROM users) u1
LEFT JOIN friendships f ON f.friend_one = u.id AND f.friend_two = u1.id
OR f.friend_one = u1.id AND f.friend_two = u.id
ORDER BY u1.id, u.id
Output:
id name password status
1 Dave 1234 me
1 John abcd pending
1 Bob xyz active
2 Dave 1234 pending
2 John abcd me
2 Bob xyz (null)
3 Dave 1234 active
3 John abcd (null)
3 Bob xyz me
Demo on SQLFiddle
To get a specific user, just add WHERE u1.id = ? before the ORDER BY clause.

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'

Decode more than on ID with two tables

TABLE PEDIDO
id_name | ID_cabimento | ID_direction
1 | 4 | 5
2 | 3 | 6
3 | 4 | 5
TABLE USER
id_name | name
1 | João
2 | Maria
3 | António
4 | Manuel
I WANT FOR RESULT
name | cabimento | direction
João | Manuel | Tozé
Maria | António | Joaquim
António | Manuel | Tozé
...
I tried UNION and JOIN but did not get the desired result... because I only can decode 1 ID.
you can join n times on same table, just using n aliases
select n.name as name, c.name as cabimento, d.name as direction
from pedido p
inner join user n on p.id_name = n.id_name
inner join user c on p.id_name = c.id_cabimento
inner join user d on p.id_name = d.id_direction