How to do an INNER JOIN without getting duplicate rows? - sql

I have two tables. A jobs table (with job.user_id) and a users table with user.id
I am trying to select all jobs and include username from users table, but I'm getting double the number of results I should be:
async getAll(context: any) {
const all = await db.queryEntries(`
SELECT j.*, u.username FROM jobs as j, users as u
INNER JOIN jobs ON jobs.user_id = u.id ORDER BY j.created_at DESC
`);
context.response.body = all;
}
I get two of everything. How do I just add 'username' where job.user_id = user.id?
users:
CREATE TABLE users (
id string primary key,
email string unique,
hashed_password string,
created_at TEXT,
updated_at TEXT,
username TEXT,
contactme INTEGER DEFAULT 1,
phone TEXT
);
jobs:
CREATE TABLE jobs (
id STRING PRIMARY KEY,
user_id STRING NOT NULL,
title STRING NOT NULL,
description STRING NOT NULL,
pay STRING NOT NULL,
type STRING NOT NULL,
created_at TEXT,
updated_at TEXT,
contact TEXT
);

I had to remove the "FROM users":
SELECT j.*, u.username FROM jobs as j
INNER JOIN users u ON j.user_id = u.id ORDER BY j.created_at DESC
This produces only one result now.

Related

Postgresql join with Condition

I have three table as follows.
CREATE TABLE users (
id uuid NOT NULL PRIMARY KEY,
password character varying(128) NOT NULL,
username character varying(15) NOT NULL,
email character varying(100) NULL,
gender character varying(1) NOT NULL
);
CREATE TABLE followers (
id bigserial NOT NULL PRIMARY KEY,
followed_at timestamp with time zone NOT NULL,
follower_id uuid REFERENCES users(id),
following_id uuid REFERENCES users(id)
);
CREATE TABLE profile_picture (
id uuid NOT NULL PRIMARY KEY ,
profile_pic character varying(100) NOT NULL,
owner_id uuid NOT NULL REFERENCES users(id),
is_active boolean NOT NULL
);
I want the query for selecting all the follower with the fields : id, username and active_profile_pic.
is_active will be true only for one profile pic of the user but he can upload as many profile photo as he want.
I have tried the without profile_pic, which is not the wanted result.
select users.id , username from users inner join followers on follower_id = users.id where followers.following_id = user_id;
I want the query for selecting all the followers with id, username and active_profile_pic who are following the user with given user_id.
User may have no profile pic and can have more than one so only the active_profile pic should be returned.
Query will have to contain the follower with no profile picture too.
Tried this, but it is not returning follower which have no profile picture. I want to return that too.
SELECT u.id, username, p.profile_pic FROM followers INNER JOIN users AS u ON u.id = follower_id
LEFT OUTER JOIN profile_picture AS p ON u.id = p.owner_id
where followers.following_id = '' and p.is_active = true
In the above query user_id signifies variable , you can specify id of the user there.
Please visit DBFIDDLE
Please suggest me the right query.
You have profile_picture.is_active test in WHERE condition, therefore your result will display only users with profile picture set. If you want all users, regardless of the profile picture, you should include profile_picture.is_active column in query results and delete the condition p.is_active = true from WHERE statement.
With the help of #random_user,
This works for me.
select id , username, profile_pic from (SELECT u.id, username, is_active, profile_pic FROM users as u Full Outer JOIN followers ON u.id = follower_id
Full Outer JOIN profile_picture AS p ON u.id = p.owner_id
where followers.following_id = '2582f93d-68c3-48e2-98ba-a401402c7b62') as profile_table where (is_active = true) or (is_active is null)
May be someone can suggest, better answer, but this works for me.
Check it at DBFIDDLE

How do I get average through ‏multiple tables

I got homework to get ‏average tags of user in album (user_id = x) in the folowing tabels:
>>> CREATE TABLE USERS (ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
NAME TEXT NOT NULL);
>>> CREATE TABLE ALBUMS (ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
NAME TEXT NOT NULL, CREATION_DATE TEXT NOT NULL,
USER_ID INTEGER REFERENCES USERS(USER_ID) NOT NULL);
>>> CREATE TABLE PICTURES (ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
NAME TEXT NOT NULL,
LOCATION TEXT NOT NULL,
CREATION_DATE TEXT NOT NULL,
ALBUM_ID INTEGER REFERENCES ALBUMS(ALBUM_ID) NOT NULL);
>>> CREATE TABLE TAGS (ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
PICTURE_ID INTEGER REFERENCES PICTURES(PICTURE_ID) NOT NULL,
USER_ID INTEGER REFERENCES USERS(USER_ID) NOT NULL);";
explenetion:
Each tag is a row in TAGS and it has picture_id, each picture has album_id and each album has user_id, basically i need to count how many times the user is tagged in each album and find the average times that the user is tagged in an album.
I can use this using only: SELECT ? FROM, AVG(), COUNT(), JOIN (INNER, LEFT, RIGHT, FULL JOIN), ON, IN, AND, OR, LIKE, , NOT, (=, != , >, <), IS, DISTINCT, ORDER BY(ASC/DESC), LIMT, OFFSET, and WHERE that means i cannot use GROUP BY
i tried this
SELECT * FROM TAGS INNER JOIN PICTURES ON tags.picture_id = PICTURES.Id where album_id IN (select id from ALBUMS where user_id = x) AND user_id = x;
but it only gives my a table that has all the tags of the user
How can i get the avg tags per album of (user_id = x), is this even possible?
First count how many times the user is tagged in each album and then get the average of these counters:
select
avg(counter) averagetags
from (
select count(t.user_id) counter
from albums a
inner join pictures p on p.album_id = a.id
inner join tags t on t.picture_id = p.id
where t.user_id = ?
group by a.id
)

Multiple selects on joined tables with group by?

I have three tables with the structures outlined below:
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(255) UNIQUE
);
CREATE TABLE posts (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT REFERENCES users(id) NOT NULL,
category BIGINT REFERENCES categories(id) NOT NULL,
text TEXT NOT NULL
);
CREATE TABLE posts_votes (
user_id BIGINT REFERENCES users(id) NOT NULL,
post_id BIGINT REFERENCES posts(id) NOT NULL
value SMALLINT NOT NULL,
PRIMARY KEY(user_id, post_id)
);
I was able to compose a query that gets each post with its user and its total value using the below query:
SELECT p.id, p.text, u.username, COALESCE(SUM(v.value), 0) AS vote_value
FROM posts p
LEFT JOIN posts_votes v ON p.id=t.post_id
JOIN users u ON p.user_id=u.id
WHERE posts.category=1337
GROUP BY p.id, p.text, u.username
But now I want to also return a column that returns the result of SELECT COALESCE((SELECT value FROM posts_votes WHERE user_id=1234 AND post_id=n), 0) for each post_id n in the above query. What would be the best way to do this?
I think an additional LEFT JOIN is a reasonable approach:
SELECT p.id, p.text, u.username, COALESCE(SUM(v.value), 0) AS vote_value,
COALESCE(pv.value, 0)
FROM posts p JOIN
users u
ON p.user_id=u.id LEFT JOIN
topics_votes v
ON p.id = t.post_id LEFT JOIN
post_votes pv
ON pv.user_id = 1234 AND pv.post_id = p.id
WHERE p.category = 1337
GROUP BY p.id, p.text, u.username, pv.value;

How to select record matchin all parameters?

I have table catalog_view. I contains contacts with assigned categories. Contacts can have several categories. I want to select contacts, which belongs to all selected by user categories
e.g contact "Jone" belongs to categories [1,2,3,4,5,6] and contact "Jay" belongs to categories [1,3]. If user select categories [2,3], only "Jone" should be returned, if [1]|[3]|[1,3] selected, both should be returned, if [7]|[1,7] selected, none should be returned.
How should I build query and/or change tables to achive it?
query wich selects contacts by single category
SELECT * FROM catalog_view WHERE (category_id = ?)
this query selects record if assigned categories matches any of those and returns number of contacts rows up to quantity of parameters, also they are not force celection to all of them.
SELECT * FROM catalog_view WHERE (category_id = ? OR category_id = ? OR category_id =?)
this query always return empty table, as row in current template for catalog_view has only one category_id
SELECT * FROM catalog_view WHERE (category_id = ? AND category_id = ? AND category_id =?)
contacts
CREATE TABLE IF NOT EXISTS contacts_table(_id integer primary key, title text default '',title_lower text default '',title_short text default '',photo blob, number text default '', note text default '', note_lower text default '', email text, partner int default '0', contact_id int default '0', current_user text default '', categories text default '', saved integer default '0' );
categories
CREATE TABLE IF NOT EXISTS categories_table(_id integer primary key, category_id integer, parent_id integer, name text, section_name text, current_user text, sub_name text default '' );
contacts with categories
CREATE TABLE IF NOT EXISTS contacts_categories_table(_id integer primary key, contact_id integer, category_id integer, current_user text );
catalog view contacts
CREATE VIEW IF NOT EXISTS catalog_view AS SELECT contacts_table._id AS _id, contacts_table.contact_id, contacts_table.title_lower, contacts_table.note_lower, contacts_table.current_user, contacts_table.saved, contacts_table.partner, contacts_table.title, contacts_table.email, contacts_table.title_short, contacts_table.number, contacts_table.note, contacts_table.categories, categories_table.section_name, contacts_table.contact_id, categories_table.parent_id, categories_table.category_id FROM contacts_categories_table INNER JOIN contacts_table ON(contacts_categories_table.contact_id = contacts_table.contact_id AND contacts_categories_table.current_user = contacts_table.current_user) LEFT OUTER JOIN categories_table ON(contacts_categories_table.category_id = categories_table.category_id AND contacts_categories_table.current_user = categories_table.current_user)
You can try something like:
SELECT distinct name from catalog_view s
where NUMBER_OF_CONTACT_SELECTION =
(SELECT count(*) from catalog_view t
where t.name = s.name and
category_id in(YOUR CONTACT SELECTION HERE IN FORMAT OF 1,3,4...))
so for 1,3 your query should be:
SELECT distinct name from catalog_view s
where 2 =
(SELECT count(*) from catalog_view t
where t.name = s.name and
category_id in(1,3))
for 1,2,4,7 it should be -> 4 = (.....IN(1,2,4,7))

How can I select data from 3 tables in sql?

I have 3 tables:
create table user (
user_id integer primary key autoincrement,
username string not null,
email string not null,
pw_hash string not null
);
create table product (
product_id integer primary key autoincrement,
productname string not null,
productdescription string not null,
);
create product_review (
product_id integer,
user_id integer,
review,
);
Now, I want to display all the reviews from user_id=1. A simple query for this would be
select * from product_review where user_id = 1
However, I want the data listed as -->
username productname review
John iPad3 Super awesome
John SonyVaio Even more awesome
Try this:
SELECT username, productname, review
FROM user a INNER JOIN product_review pr
ON a.user_id = pr.user_id INNER JOIN product p
ON p.product_id = pr.product_id
WHERE a.user_id = 1