Postgresql request to get recommended friends - postgresql

I have two tables, friends and relations of friends:
Friendship is symmetrical.
CREATE TABLE t_users (
user_id varchar PRIMARY KEY,
name varchar
);
CREATE TABLE t_friendship (
friendship_id varchar PRIMARY KEY,
from_user_id varchar,
to_user_id varchar
);
INSERT INTO t_users VALUES ('us123', 'us123');
INSERT INTO t_users VALUES ('us456', 'us456');
INSERT INTO t_users VALUES ('us789', 'us789');
INSERT INTO t_users VALUES ('us987', 'us987');
INSERT INTO t_users VALUES ('us654', 'us654');
INSERT INTO t_users VALUES ('us321', 'us321');
INSERT INTO t_friendship VALUES ('fr123', 'us123', 'us456');
INSERT INTO t_friendship VALUES ('fr456', 'us123', 'us789');
INSERT INTO t_friendship VALUES ('fr789', 'us123', 'us987');
INSERT INTO t_friendship VALUES ('fr987', 'us456', 'us123');
INSERT INTO t_friendship VALUES ('fr654', 'us456', 'us321');
INSERT INTO t_friendship VALUES ('fr321', 'us987', 'us123');
INSERT INTO t_friendship VALUES ('fr322', 'us456', 'us654');
INSERT INTO t_friendship VALUES ('fr323', 'us654', 'us123');
INSERT INTO t_friendship VALUES ('fr324', 'us789', 'us654');
INSERT INTO t_friendship VALUES ('fr325', 'us321', 'us123');
How to make a request to get recommended friends.
For example friends of my friends.
Thank you.

Related

How to pull out records based on array of values

Suppose the following structure:
CREATE SCHEMA IF NOT EXISTS my_schema;
CREATE TABLE IF NOT EXISTS my_schema.user (
id SERIAL PRIMARY KEY,
tag_id BIGINT NOT NULL
);
CREATE TABLE IF NOT EXISTS my_schema.conversation (
id SERIAL PRIMARY KEY,
user_ids BIGINT[] NOT NULL
);
INSERT INTO my_schema.user VALUES
(1, 55555),
(2, 77777);
INSERT INTO my_schema.conversation VALUES
(1, '{1,2}');
I can pull out the my_schema.conversation records if I know the my_schema.user.id values:
SELECT *
FROM my_schema.conversation
WHERE user_ids #> '{1}'
The above works, but I need to use my_schema.user.tag_id instead of my_schema.user.id:
How can I do this?
Fiddle
You would have to join the two tables on the array values
SELECT *
FROM my_schema.user u
JOIN my_schema.conversation c
ON u.id = any(c.chat_ids)
WHERE u.tag_id=55555;

Postgresql not choosing rows grouping

I have query. There is a construction like this example: (online demo)
You will see the in result created_at field. I have to use query the created_at field. So I have to use it in select created_at. I don't want to use it created_at field in select. Because, there are millions of records in the deposits table. How can i escape this problem?
(Note: I have many table to query, like "deposits" table. this is just a short example.)
create table payment_methods
(
payment_method_id bigserial not null
constraint payment_methods_pkey
primary key
);
create table currencies_of_payment_methods
(
copm_id bigserial not null
constraint currencies_of_payment_methods_pkey
primary key,
payment_method_id integer not null
);
create table deposits
(
deposit_id bigserial not null
constraint deposits_pkey
primary key,
amount numeric(18,2) not null,
copm_id integer not null,
created_at timestamp(0)
);
INSERT INTO payment_methods (payment_method_id) VALUES (1);
INSERT INTO payment_methods (payment_method_id) VALUES (2);
INSERT INTO currencies_of_payment_methods (copm_id, payment_method_id) VALUES (1, 1);
INSERT INTO deposits (amount, copm_id, created_at) VALUES (100, 1, '2020-09-10 08:49:37');
INSERT INTO deposits (amount, copm_id, created_at) VALUES (200, 1, '2020-09-10 08:49:37');
INSERT INTO deposits (amount, copm_id, created_at) VALUES (40, 1, '2020-09-10 08:49:37');
Query:
SELECT payment_methods.payment_method_id,
deposit_copm_id.deposit_copm_id,
manuel_deposit_amount.manuel_deposit_amount,
manuel_deposit_amount.created_at
FROM payment_methods
CROSS JOIN lateral
(
SELECT currencies_of_payment_methods.copm_id AS deposit_copm_id
FROM currencies_of_payment_methods
WHERE currencies_of_payment_methods.payment_method_id = payment_methods.payment_method_id) deposit_copm_id
CROSS JOIN lateral
(
SELECT sum(deposits.amount) AS manuel_deposit_amount,
array_agg(deposits.created_at) AS created_at
FROM deposits
WHERE deposits.copm_id = deposit_copm_id.deposit_copm_id) manuel_deposit_amount
WHERE payment_methods.payment_method_id = 1

select columns in select query from another mapping table

I am looking for select query with dynamic column names that can be derived from another table. Below the sample data and query I am looking to get.
create table mapping_tmp (
string_number varchar,
mapping_name varchar
)
create table fact_tmp (
product varchar,
product_family varchar,
string1 varchar,
string2 varchar,
string3 varchar,
string4 varchar,
string5 varchar
)
insert into mapping_tmp values ('string1','commodity');
insert into mapping_tmp values ('string2','real commodity');
insert into mapping_tmp values ('string3','country');
insert into mapping_tmp values ('string4','region');
insert into mapping_tmp values ('string5','area');
insert into fact_tmp values ('P1','PF1','ABC1','DEF1','GHI1','JKL1','MNO1');
insert into fact_tmp values ('P2','PF2','ABC2','DEF2','GHI2','JKL2','MNO2');
insert into fact_tmp values ('P3','PF3','ABC3','DEF3','GHI3','JKL3','MNO3');
insert into fact_tmp values ('P4','PF4','ABC4','DEF4','GHI4','JKL4','MNO4');
insert into fact_tmp values ('P5','PF5','ABC5','DEF5','GHI5','JKL5','MNO5');
insert into fact_tmp values ('P6','PF6','ABC6','DEF6','GHI6','JKL6','MNO6');
Expected output, select fields should be taken from mapping_tmp and those fields data should be displayed in select result.
select product,
(select string_number from mapping_tmp where mapping_name = 'country') as country,
(select string_number from mapping_tmp where mapping_name = 'area') as area
from fact_tmp;
The actual query is
select product, string3 as country, string5 as area from fact_tmp;
and the output:
product country area
1 P1 GHI1 MNO1
2 P2 GHI2 MNO2
3 P3 GHI3 MNO3
4 P4 GHI4 MNO4
5 P5 GHI5 MNO5
6 P6 GHI6 MNO6
I am looking for simple sql query, I cannot use stored procedure or function in application.

Inner join request to get the items available for the user

I have four tables:
CREATE TABLE t_users (
user_id varchar PRIMARY KEY,
user_email varchar
);
CREATE TABLE t_items (
item_id varchar PRIMARY KEY,
owner_id varchar not null references t_users(user_id),
title varchar
);
CREATE TABLE t_access_gropes (
access_group_id varchar PRIMARY KEY,
user_id varchar not null references t_users(user_id)
);
CREATE TABLE t_access_sets (
access_set_id varchar PRIMARY KEY,
item_id varchar not null references t_items(item_id),
access_group_id varchar not null references t_access_gropes(access_group_id)
);
With data:
INSERT INTO t_users VALUES ('us123', 'us123#email.com');
INSERT INTO t_users VALUES ('us456', 'us456#email.com');
INSERT INTO t_users VALUES ('us789', 'us789#email.com');
INSERT INTO t_items VALUES ('it123', 'us123', 'title1');
INSERT INTO t_items VALUES ('it456', 'us456', 'title2');
INSERT INTO t_items VALUES ('it678', 'us789', 'title3');
INSERT INTO t_items VALUES ('it323', 'us123', 'title4');
INSERT INTO t_items VALUES ('it764', 'us456', 'title5');
INSERT INTO t_items VALUES ('it826', 'us789', 'title6');
INSERT INTO t_items VALUES ('it568', 'us123', 'title7');
INSERT INTO t_items VALUES ('it038', 'us456', 'title8');
INSERT INTO t_items VALUES ('it728', 'us789', 'title9');
INSERT INTO t_access_gropes VALUES ('ag123', 'us123');
INSERT INTO t_access_gropes VALUES ('ag456', 'us456');
INSERT INTO t_access_gropes VALUES ('ag789', 'us789');
INSERT INTO t_access_sets VALUES ('as123', 'it123', 'ag123');
INSERT INTO t_access_sets VALUES ('as456', 'it456', 'ag123');
The t_access_gropes forms groups of users.
The t_access_sets forms security kits.
How to make a request to get the all items available for the user. Something like:
select *
from t_items
inner join t_users on t_items.owner_id = t_users.user_id
inner join t_access_gropes on t_users.user_id = t_access_gropes.user_id
inner join t_access_sets on t_items.item_id = t_access_sets.item_id
where t_access_gropes.user_id = 'us123';
Thank you.
select u.user_id, u.email, i.item_id, i.title
from t_users u
join t_items i on i.owner_id = u.user_id
where u.user_id = 'us123'
I believe this is what you want for your exact request!
Otherwise what you wrote is fine however I dont see the relevance in the tables you joined together as you directly connected your users table and items table together, which is why you wouldnt need to join the other two tables (groups & sets). Usually in some cases you find a table of user_items inbetween the users and items table.

PostgreSQL: dynamically create result columns

I want to "dynamically" create the result columns in a PostgreSQL query. I have these tables:
CREATE SEQUENCE users_id;
CREATE TABLE users (
id INT PRIMARY KEY NOT NULL DEFAULT NEXTVAL('users_id'),
name VARCHAR(128) NOT NULL
);
CREATE SEQUENCE quota_rules_id;
CREATE TABLE quota_rules (
id INT PRIMARY KEY NOT NULL DEFAULT NEXTVAL('quota_rules_id'),
user_id INT REFERENCES users(id),
rule VARCHAR(255) NOT NULL
);
CREATE INDEX user_id_index ON quota_rules(user_id);
INSERT INTO users (name) VALUES ('myname'); -- id=1
INSERT INTO quota_rules (user_id, rule) VALUES (1, 'a');
INSERT INTO quota_rules (user_id, rule) VALUES (1, 'b');
INSERT INTO quota_rules (user_id, rule) VALUES (1, 'c');
And want a query that returns this (1 row):
SELECT ............ user_id = 1;
name | quota_rule | quota_rule2 | quota_rule3
myname | a | b | c
Check out the crosstab function of the tablefunc module