Add join to display items based on key - sql

I have these Postgres tables:
create table employees
(
id bigint primary key,
account_id number,
first_name varchar(150),
last_name varchar(150)
);
create table accounts
(
id bigint primary key,
account_name varchar(150) not null
);
I need to search in table employees by account_id and print result the rows which match in table accounts.id. How I can do this using JOIN?

I'm pretty sure this is what you're looking for.
SELECT a.id, a.account_name, e.first_name, e.last_name
FROM employees as e
JOIN accounts as a on a.id = e.account_id
WHERE e.account_id = 3
This will allow you to search for specific account IDs in the employee table and bring back their corresponding account table information.
You can check this with my dbfiddle here - https://www.db-fiddle.com/f/pwzwQTsHuP27UDF17eAQy4/0

Related

Join columns to search string

I have these tables which I would like to query:
create table employees
(
id bigint generated by default as identity (maxvalue 2147483647),
username varchar(100) not null,
password varchar(60) not null,
account_id bigint,
role_id bigint,
first_name varchar(150),
last_name varchar(150),
primary key (id)
);
create table accounts
(
id bigint generated by default as identity,
account_name varchar(150) not null,
account_group_id bigint not null,
primary key (id)
);
Test data:
insert into employees (id, username, password, account_id) values
(1, "test user", "pass", 3),
(2, "test user2 ", "pass", 4);
insert into accounts (id, account_name, account_group_id) values
(1, "main", 3),
(2, "second", 4);
(3, "third", 4);
I need to create a query which searches into table employees by account_name. I tried this:
Example when I send search param second I need to get a row result: test user2
SELECT * FROM common.employees e
WHERE e.??????? iLIKE CONCAT('%', :params, '%')
Do you know how I can join the tables?
You cannot directly parameterize Sql identifier(columns, tables), You can only parameterize values.
Prepared statements can take parameters: values that are substituted into the statement when it is executed.
https://www.postgresql.org/docs/current/sql-prepare.html
In your code. WHERE e.??????? cannot be easily parameterized. You need to use plpgsql functions.
prepare test(text,int) as SELECT e.* FROM employees e
join accounts a on e.account_id = a.id
WHERE a.account_name iLIKE CONCAT('%', $1, '%')
and a.account_group_id = $2;
If your already have test prepare statement in the active session then DEALLOCATE test;
suppose the account_group_id = 1 then:
execute test('third', 1);
Join the 2 tables like that (result here)
SELECT e.* FROM
employees e, accounts a
WHERE
e.account_id = a.id
and a.account_name = 'second'
To include columns account_group_id and account_id into the result you can get as below :
Though e.* will contain all the info that is present in employee table which include account_id as well. So if you want to customized your result set you can do that according to your need:
SELECT e.*,a.account_group_id
FROM employees e
INNER JOIN accounts a ON a.id = e.account_id
WHERE a.account_name = param
If you just use an inner join and join on the account table using the account_id and add a WHERE clause where you only select from employee where the account_name equals your param....which I'm guessing will be a varchar
SELECT e.*, a.account_group_id
FROM employees e
INNER JOIN accounts a ON a.id = e.account_id
WHERE a.account_name = param
or
WHERE a.account_name LIKE '%param%'
but the second may bring back other users as the param could exist in other names.
Also I don't believe the data in your example is correct as surely the account_id would link to the id in the accounts table...so passing second would in fact get you an employee who's account_id is 2.

Get user from table based on id

I have these Postgres tables:
create table deals_new
(
id bigserial primary key,
slip_id text,
deal_type integer,
timestamp timestamp,
employee_id bigint
constraint employee_id_fk
references common.employees
);
create table twap
(
id bigserial primary key,
deal_id varchar not null,
employee_id bigint
constraint fk_twap__employee_id
references common.employees,
status integer
);
create table employees
(
id bigint primary key,
account_id integer,
first_name varchar(150),
last_name varchar(150)
);
New table to query:
create table accounts
(
id bigint primary key,
account_name varchar(150) not null
);
I use this SQL query:
select d.*, t.id as twap_id
from common.deals_new d
left outer join common.twap t on
t.deal_id = d.slip_id and
d.timestamp between '11-11-2021' AND '11-11-2021' and
d.deal_type in (1, 2) and
d.quote_id is null
where d.employee_id is not null
order by d.timestamp desc, d.id
offset 10
limit 10;
How I can extend this SQL query to search also in table employees by account_id and map the result in table accounts by id? I would like to print also accounts. account_name based on employees .account_id.
You need two joins to to make this work for you. One join to get to the employee table, and one more join to get to the accounts table.
select d.*, t.id as twap_id, a.account_name
from common.deals_new d
left outer join common.twap t on
t.deal_id = d.slip_id and
d.timestamp between '11-11-2021' AND '11-11-2021' and
d.deal_type in (1, 2) and
d.quote_id is null
join employees as e on d.employee_id = e.id
join accounts as a on a.id = e.account_id
where d.employee_id is not null
order by d.timestamp desc, d.id
offset 10
limit 10;
Note: I did not fiddle this one, so could have a typo, but I think you get the idea here.

PostgreSQL query for Library Management System

Get the member ID and name of the members to whom no more books can be issued, because they have already got as many books issued as the number for which they are entitled
Following are the schemas:
Book_Records(accession_no,isbn_no)
Book(isbn_no, author, publisher, price)
Members(member_id, member_name,max_no_books,max_no_days)
Book_Issue(member_id,accession_no,issue_date,return_date)
CREATE TABLE BOOK (ISBN_NO VARCHAR(35) PRIMARY KEY,
AUTHOR VARCHAR(35) NOT NULL,
PUBLISHER VARCHAR(35) NOT NULL,
PRICE NUMERIC(10,3));
CREATE TABLE BOOK_RECORDS(ACCESSION_NO VARCHAR(35) PRIMARY KEY,
ISBN_NO VARCHAR(35) REFERENCES BOOK(ISBN_NO));
CREATE TABLE MEMBERS(MEMBER_ID VARCHAR(35) PRIMARY KEY,
MEMBER_NAME VARCHAR(35) NOT NULL,
MAX_NO_BOOKS INT,
MAX_NO_DAYS INT);
CREATE TABLE BOOK_ISSUE(MEMBER_ID VARCHAR(35) REFERENCES MEMBERS(MEMBER_ID),
ACCESSION_NO VARCHAR(35) REFERENCES
BOOK_RECORDS(ACCESSION_NO),
ISSUE_DATE DATE NOT NULL,
RETURN_DATE DATE,
PRIMARY KEY(MEMBER_ID,ACCESSION_NO));
I tried the following query but fails.
SELECT DISTINCT member_name
FROM members AS m
JOIN (
SELECT member_id, COUNT(*) AS no_books_issued
FROM book_issue
GROUP BY member_id,accesion_no
HAVING no_books_issued >= max_no_books
) AS b ON m.member_id = b.member_id;
Presumably, a query like this gets the number of books currently issued:
SELECT member_id, COUNT(*) AS num_books
FROM book_issue
WHERE return_date IS NULL
GROUP BY member_id;
My understanding of the maximum number of books would be concurrently -- that is, only count books that have not been returned. Perhaps you have a different definition.
Then, you can use this in a JOIN, doing the comparison on the maximum outside the subquery:
SELECT member_name
FROM members m JOIN
(SELECT member_id, COUNT(*) AS num_books
FROM book_issue
WHERE return_date IS NULL
GROUP BY member_id
) b
ON b.member_id = m.member_id AND
b.num_books >= m.max_no_books;
Notes:
In a JOIN, the comparison to the outer table needs to be outside the subqueries.
No SELECT DISTINCT is needed.
The GROUP BY for counting books should be only at the member level.

How to simplify nested select in where clause?

I have 4 tables EMPLOYEE, COMPANY, WORKS and MANAGES. The tables are defined as follows-
CREATE TABLE EMPLOYEE
(
EMPLOYEE_NAME VARCHAR2(50) NOT NULL PRIMARY KEY,
STREET VARCHAR2(50) NOT NULL,
CITY VARCHAR2(30) NOT NULL
);
CREATE TABLE COMPANY
(
COMPANY_NAME VARCHAR2(100) NOT NULL PRIMARY KEY,
CITY VARCHAR2(50) NOT NULL
);
CREATE TABLE WORKS
(
EMPLOYEE_NAME VARCHAR2(50) NOT NULL PRIMARY KEY REFERENCES EMPLOYEE(EMPLOYEE_NAME),
COMPANY_NAME VARCHAR2(100) NOT NULL REFERENCES COMPANY(COMPANY_NAME),
SALARY NUMBER(12,2) NOT NULL
);
CREATE TABLE MANAGES
(
EMPLOYEE_NAME VARCHAR2(50) NOT NULL PRIMARY KEY REFERENCES EMPLOYEE(EMPLOYEE_NAME),
MANAGER_NAME VARCHAR2(50) NOT NULL
);
I need to find all the employees who live in the same city as the company for which they work. So far I have done this.
SELECT EMPLOYEE_NAME AS Names
FROM EMPLOYEE
WHERE CITY = (
SELECT CITY
FROM COMPANY
WHERE COMPANY_NAME = (
SELECT COMPANY_NAME
FROM WORKS
WHERE WORKS.EMPLOYEE_NAME = EMPLOYEE.EMPLOYEE_NAME
)
);
It's working fine. But I want to know is there any simpler way to do this query?
You could use an explicit inner join instead of nested subselect
SELECT EMPLOYEE.EMPLOYEE_NAME AS Names
FROM EMPLOYEE
INNER JOIN WORKS ON WORKS.EMPLOYEE_NAME = EMPLOYEE.EMPLOYEE_NAME
INNER JOIN COMPANY ON EMPLOYEE.CITY = COMPANY.CITY
SELECT EMPLOYEE.EMPLOYEE_NAME As Names
FROM EMPLOYEE
INNER JOIN WORKS ON WORKS.EMPLOYEE_NAME = EMPLOYEE.EMPLOYEE_NAME
INNER JOIN COMPANY ON COMPANY.COMPANY_NAME = WORKS.COMPANY_NAME
WHERE COMPANY.CITY = EMPLOYEE.CITY
This is essentially what Ken White was suggesting using the inner join.
You mention a WHERE clause so you could do:
SELECT e.EMPLOYEE_NAME As Names
FROM EMPLOYEE e
WHERE e.CITY = (SELECT c.CITY
FROM Company c JOIN
Works w
ON c.COMPANY_NAME = w.COMPANY_NAME
WHERE w.EMPLOYEE_NAME = e.EMPLOYEE_NAME
);
Notes:
This assumes that employees only work for one company. Otherwise, the subquery could return multiple rows. You can handle this situation by changing the = to IN.
Names are a really bad key to use for foreign key relationships. Usually numeric ids are better. What happens if an employee or company changes names?
Table aliases make a query easier to write and to read.
select employee.employee_name
from company, employee, works
where company.company_name=works.company_name
and works.employee_name=employee.employee_name
and employee.city = company.city

SELECT value from a second level foreign key table

Greetings fellow Earthlings,
I have a problem. Let me start by laying out my table structure:
CREATE TABLE Person
(
id varchar(50) NOT NULL PRIMARY KEY,
name varchar(50) NOT NULL,
adress varchar(50) NOT NULL references Adress(id)
)
CREATE TABLE Adress
(
id varchar(50) NOT NULL PRIMARY KEY,
addressName varchar(50),
city varchar(50),
aState varchar(50),
linkToCountry varchar(50) references Country(id)
)
CREATE TABLE Country
(
id varchar(50) NOT NULL PRIMARY KEY,
countryName varchar(50)
)
What I want to achieve is: select a person 'name' along with their 'addressName' and the 'countryName' they're from.
I know that this is a joining related issue but I can't seem to figure this one out.
So any help from people who are well versed on SQL?
Would appreciate it very very much any one has links to advance sql joining so I can familiarize myself with it.
You can get the result using simple join as below. This will retrun the person name with address name, and country name. However it returns only those person names which has an address record in the address table and country record in the country table. If you want to retrieve all the persons irrespective of whether address/country exists or not, you need to use left join.
SELECT Person.Name, Address.addressname,Country.countryName
FROM Person
JOIN Address on Person.address = Address.Id
JOIN Country ON Address.linkToCountry = Country.id
Try this:
SELECT p.name, a.addressName, c.countryName
FROM Person p
INNER JOIN Adress a ON p.adress = a.id
LEFT OUTER JOIN Country c ON a.linkToCountry = c.id