Postgres Query to join two tables - postgresql

I have two tables in Postgres database. In each table there is a column which represent same number. I have tried few join queries to join both tables with similar column numbers but none of them are giving me the expected output.
user_id column from Table 1 is equal to Id column in Table 2
How can join these two tables?
I have tried below and some other queries as well but it didn't get what I wanted
SELECT members.access_level, members.user_id FROM members INNER JOIN users ON members.user_id = users.id;
Tables columns looks like below,
Members table
id |access_level |source_id |user_id |type
Users Table
id |email |name |username
Query output should look as below:
username |name |email |access_level

SELECT u.username
, u.name
, u.email
, m.access_level
FROM users u
JOIN members m ON (u.id = m.user_id)
;
If you want users that are not included in the members table you can join with a LEFT JOIN
To address your question asked in the comments I believe you'd be looking for something like the following:
UPDATE members SET access_level = 'dev' WHERE access_level = '30';
This is assuming that the column is already of type text. Otherwise, you'll need to change the data type first using the following:
ALTER TABLE members
ALTER access_level SET DATA TYPE text;

SELECT users.*, members.user_id, members.acces_level
FROM members
LEFT JOIN users
WHERE users.id = members.user_id

Related

join on 4 tables each with two columns needing to join to one column on a base table

I have 3 tables that each have a created_by and modified_by column. Those columns have a user_id that maps to a user_mstr table where I can get the actual names of the users.
I am stuck on how to get the created_by and modified_by (which can be different users for each column within a table and for each of the 3 tables joining to) joined to the user_mstr table.
select tv.created_by as VitalsCreatedBy, tv.modified_by as VitalsModifiedBy,
td.created_by as DiabScreenCreatedBy, td.modified_by as DiabScreenModifiedBy,
ds.created_by as DiabFootScreenCreatedBy, ds.modified_by as DiabFootScreenModifiedBy,
phq.created_by as PHQCreatedBy, phq.modified_by as PHQModifiedBy
left join user_mstr um on tv.created_by = um.user_id and tv.modified_by = um.user_id
Just not sure how to get them all joined properly.
Essentially you need to join the table for each UserId, or you could use an inline sub-query for each User name which can make it easier to manage if you have a large number of audit columns to display:
select
(select um.UserName from user_mstr um where um.user_id=tv.created_by) as VitalsCreatedBy,
(select um.UserName from user_mstr um where um.user_id=tv.modified_by) as VitalsModifiedBy,
(select um.UserName from user_mstr um where um.user_id=td.created_by) as DiabScreenCreatedBy
...
from ...

Postgres SQL array aggregate values from a single table based on conditions

I'm a SQL newbie and I'm trying to write the following query:
I have the following table:
user_id | chat_id
---------+---------
Which represents a many to many mapping of users to chat rooms;
I'm looking to create a query that finds all the chat_ids that are associated with the input user_id, and then array aggregates all the user_ids associated with those chats excluding the input user_id.
So the result should look like this for example:
chat_id | user_id
---------+---------
1 {1,3,5,6}
I've kind of jumbled together to following query; but I'm pretty sure I got something wrong:
WITH chatIDs AS (SELECT user_chats.chat_id FROM user_chats WHERE user_chats.user_id=$1)
WITH userIDs AS (SELECT user_chats.user_id FROM user_chats WHERE user_chats.chat_id=chatIDs AND user_chats.user_id != $1)
SELECT chatIDs, array_agg(userIDs) FROM user_chats;
EDIT:
Edited for clarity
I believe you could just use a where clause to exclude the user:
SELECT chat_id, array_agg(user_id) FROM user_chats
WHERE user_id != $1 AND chat_id IN (SELECT chat_id FROM user_chats WHERE user_id = $1)
GROUP BY chat_id

Join two postgresql queries

I have the following query
SELECT role_uuid FROM users WHERE email = 'email#domain.com'
I also have a roles table the following fields:
uuid
name
created_at
I'm hoping to have 1 query that gives lets me select the role by email and get the name and created_at field from the roles table.
I've tried things like this but I can't quite figure it out.
SELECT *
FROM ( SELECT * FROM users WHERE email = 'email#domain.com') AS A
JOIN ( SELECT * FROM roles WHERE uuid = A.role_uuid) AS B
WHERE A.role_uuid = B.uuid
You JOIN the two tables which gives you a table with all the fields from both source tables. Then you use WHERE to filter and SELECT to specify the fields that you want to be returned.
SELECT r.name, r.created_at
FROM users u JOIN roles r ON (u.role_uuid = r.uuid)
WHERE u.email = 'email#domain.com'
If you run into naming conflicts because of fields from both tables sharing the same name you can use AS to define fieldnames for the output columns:
SELECT r.name AS rolename, u.name AS username, r.created_at
FROM users u JOIN roles r ON (u.role_uuid = r.uuid)
WHERE u.email = 'email#domain.com'

show records that have only one matchin row in another table

I need to write a sql code that probably is very simple but I am very new to it.
I need to find all the records from one table that have matching id (but no more than one) from the other table. eg. one table contains records of the employees and the second one with employees' telephone numbers. i need to find all employees with only one telephone no
Sample data would be nice. In absence of:
SELECT
employees.employee_id
FROM
employees
LEFT JOIN
(SELECT distinct on(employee_id) employee_id FROM emp_phone) AS phone
ON
employees.employee_id = phone.employee_id
WHERE
phone.employee_id IS NOT NULL;
You need a join of the 2 tables, group by employee and the condition in the having clause:
SELECT e.employee_id, e.name
FROM employees e INNER JOIN numbers n
ON e.employee_id = n.employee_id
GROUP BY e.employee_id, e.name
HAVING COUNT(*) = 1;
If there can be more than a few numbers per employee in the table with the employees' telephone numbers (calling it tel), then it's cheaper to avoid GROUP BY and HAVING which has to process all rows. Find employees with "unique" numbers using a self-anti-join with NOT EXISTS.
While you don't need more than the employee_id and their unique phone number, you don't even have to involve the employee table at all:
SELECT *
FROM tel t
WHERE NOT EXISTS (
SELECT FROM tel
WHERE employee_id = t.employee_id
AND tel_number <> t.tel_number -- or use PK column
);
If you need additional columns from the employee table:
SELECT * -- or any columns you need
FROM (
SELECT employee_id AS id, tel_number -- or any columns you need
FROM tel t
WHERE NOT EXISTS (
SELECT FROM tel
WHERE employee_id = t.employee_id
AND tel_number <> t.tel_number -- or use PK column
)
) t
JOIN employee e USING (id);
The column alias in the subquery (employee_id AS id) is just for convenience. Then the outer join condition can be USING (id), and the ID column is only included once in the result, even with SELECT * ...
Simpler with a smart naming convention that uses employee_id for the employee ID everywhere. But it's a widespread anti-pattern to use employee.id instead.
Related:
JOIN table if condition is satisfied, else perform no join

DQl JOIN and WHERE

I'm trying to get query like this:
SELECT * FROM `users` u JOIN clientdetails d WHERE u.id = d.id AND d.staff_id =?
so I wrote DQL:
SELECT u FROM PswAdminBundle:User u JOIN PswAdminBundle:ClientDetails d WHERE d.staffRep=?0
but resulting query is
SELECT * FROM users u0_ INNER JOIN ClientDetails c1_ ON (c1_.staff_id = ?)
May it be because these two tables have 2 relations between them?
In users table I keep all users of app(clients and staff) records representing clients have relation one to one with table clientdetails using id from both tables. In clientdetails I have column staff_id that goes back to user table pointing on record representing staff user.
I'm trying to fetch all clients that are related to staff.