Is there a way to select this name from more than one table? - sql

I need to select the item name and the vendor name for each item that belongs to the vendor with a rating bigger than 4. And I can't find a way, I know it's something with joins but the 2 of them have the same column name.
CREATE TABLE venedors(
id int PRIMARY KEY,
name varchar2(20),
rating int)
CREATE TABLE items(
id int PRIMARY KEY,
name varchar2(20),
venedorId int references venedors(id))

If i understanded your problem.
Select items.name as itemName, venedors.name as vendorName
from items
inner join venedors
on items.venedorId = venedors.id
where venedors.rating > 4

If you want get all the vendors irrespective whether there are items associated with vendors or not, then try with left join as shown below:
Select v.name as vendorName, i.name as itemName
from venedors v
left join items i
on i.venedorId = v.id
where v.rating > 4

Related

SQL insert multiple rows depending on number of rows returned from subquery

I have 3 SQL tables Companies, Materials and Suppliers as follows.
Tables
I need to insert values into Suppliers from a list which contains Company Name and Material Name as headers. However, I have multiple companies with the same name in the database and i need to add a new value into suppliers for each one of those companies.
For e.g. my list containes values ['Wickes','Bricks'] . I have this sql below to add a new entry into the suppliers table but since i have multple companies called 'Wickes' I'll get an error as the subquery will return more than 1 value.
INSERT INTO Suppliers(Id,CompanyId,MaterialId) VALUES (NEWID(), (SELECT Id FROM Companies WHERE Name = 'Wickes'),(SELECT Id FROM Materials WHERE Name = 'Bricks'))
Whats the best solution to get the Id of all the companies there are called 'Wickes' and then add vales into the suppliers table with that Id and the relevant material Id of 'Bricks'.
You can use INSERT () SELECT.. rather than INSERT () VALUES(), e.g
INSERT INTO Suppliers (Id, CompanyId, MaterialId)
SELECT NEWID(), c.Id, m.Id
FROM Companies AS c
CROSS JOIN Materials AS m
WHERE c.Name = 'Wickes'
AND m.Name = 'Bricks';
This will ensure that if you have multiple companies/materials with the same name, all permutations are inserted. Example on db<>fiddle
Although based on your image Suppliers.Id is an integer, so I think NEWID() is not doing what you think it is here, you probably just want:
INSERT INTO Suppliers (CompanyId, MaterialId)
SELECT c.Id, m.Id
FROM Companies AS c
CROSS JOIN Materials AS m
WHERE c.Name = 'Wickes'
AND m.Name = 'Bricks';
And let IDENTITY take care of the Id column in Suppliers.
As a further aside, I've also just noted that MaterialId is VARCHAR in your Suppliers table, that looks like an error if it is supposed to reference the integer Id column in Materials.
INSERT INTO Suppliers(Id,CompanyId,MaterialId) VALUES (NEWID(), (SELECT distict Id FROM Companies WHERE Name = 'Wickes'),(SELECT distict Id FROM Materials WHERE Name = 'Bricks'));
If I understand rightly Companies are the suppliers and the Suppliers table is the one that says where you can buy each material from.
Why do you have duplicates? Do you have an account for different branches of Wickes for example? If they are really duplicates and you don't care which one you use a function like MIN() will do the job of ensuring that only one value is returned. If you have duplicates it would be a good idea to find a way of disactivating all except one. This will make is simpler for you everytime you want to deal with the supplier: minimum orders, chasing overdue orders, payments etc.
Also Companies.ID and Materials.ID should be foreign keys of the Suppliers table. It is also a good idea for the ID column to be auto-incrementing, which makes it easier to add new products as you do not need to specify the ID column.
If you cannot or do not want to modify the id column to auto-incrementing IDENTITY you can continue to use NEWID().
create table Companies(
id INT PRIMARY KEY NOT NULL IDENTITY,
name VARCHAR(25));
create table Materials(
id INT PRIMARY KEY NOT NULL IDENTITY,
name VARCHAR(25));
create table Suppliers(
id INT PRIMARY KEY NOT NULL IDENTITY,
CompanyId INT FOREIGN KEY REFERENCES Companies(id),
MaterialId INT FOREIGN KEY REFERENCES Materials(id)
);
INSERT INTO Companies (name) VALUES ('Wickes');
INSERT INTO Materials (name) VALUES ('Bricks');
INSERT INTO Suppliers ( CompanyId, MaterialId)
SELECT c.Id, M.Id
FROM Companies AS c
CROSS JOIN Materials AS m
WHERE c.Name = 'Wickes'
AND m.Name = 'Bricks';
SELECT * FROM Companies;
SELECT * FROM Materials;
SELECT * FROM Suppliers;
GO
id | name
-: | :-----
1 | Wickes
id | name
-: | :-----
1 | Bricks
id | CompanyId | MaterialId
-: | --------: | ---------:
1 | 1 | 1
db<>fiddle here
INSERT INTO SUPPLIERS
(ID, COMPANYID, MATERIALID)
VALUES (NEWID(),
(SELECT DISTINCT ID FROM COMPANIES WHERE NAME = 'Wickes'), (SELECT DISTINCT ID FROM MATERIALS WHERE NAME = 'Bricks'))

SQL Query to check if a record does not exist in another table

I have a table which holds details of all Students currently enrolled in classes which looks like this:
CREATE TABLE studentInClass(
studentID int,
classID int,
FOREIGN KEY(studentID) references students(studentID),
foreign key(classID) references class(classID)
);
And another table which contains details of students who have paid for classes:
CREATE TABLE fees(
feesID INTEGER PRIMARY KEY AUTOINCREMENT,
StudentID INTEGER,
AmountPaid INT,
Date DATE,
FOREIGN KEY(StudentID) REFERENCES students(StudentID));
What I want to do is check whether a student who is in a class has not paid for that class. I am struggling to write a SQL query which does so. I have tried multiple queries such as:
Select studentInClass.StudentID
from fees, studentInClass
where fees.StudentID = studentInClass.StudentID;
But this returns no data. I'm not sure how to proceed from here. Any help will be appreciated.
You want outer join :
select s.StudentID, (case when f.AmountPaid is not null
then 'Yes'
else 'No'
end) as Is_fees_paid
from studentInClass s left join
fees f
on f.StudentID = s.StudentID;
With NOT EXISTS:
select s.*
from studentInClass s
where not exists (
select 1 from fees
where studentid = s.studentid
)
with this you get all the rows from the table studentInClass for which there is not the studentid in the table fees.
It's not clear if you also need to check the date.
check it please:
select studentInClass.StudentID
from studentInClass inner join fees ON fees.StudentID = studentInClass.StudentID

Selecting a subset of columns

I am using sqllite to create two tables
CREATE TABLE NAMES(Id integer PRIMARY KEY, Name text);
CREATE TABLE PHONE(Id inetegr PRIMARY KEY, PersonID integer, Number integer,
FOREIGN KEY (PersonID) REFERENCES NAMES(Id)
);
Then, I have written a qry to slect all people having more than 2 phones
select count(PersonID) as counts,Name
from PHONE
INNER JOIN NAMES on NAMES.Id=PHONE.PersonID
group by PersonID
having counts>=2;
The output is like below
2|Tom
However, I dont want to print the count and just need the names, how to change my query to just print the name..
you can try like below
select Name from PHONE
INNER JOIN NAMES on NAMES.Id=PHONE.PersonID
group by Name
having count(distinct Number)>=2;
You can try below
select Name from PHONE
INNER JOIN NAMES on NAMES.Id=PHONE.PersonID
group by Name having count(PersonID)>=2;

Create tables with Many-to-One relation in Postgresql

I am a newbie with Postgresql and database . I have the following table Shop
Create table Shop(
id integer ,
Name varchar(50),
Adress varchar(50) )
And I have a second table Product
Create table Product(
id integer ,
Name varchar(50),
Price float)
How to create a relation One-To-One between Product and Shop ?
Use a separate table, called a junction table or join table (and unfortunately has many other names)
CREATE TABLE Products_in_shop (
shop_id INTEGER,
product_id INTEGER
)
You can then JOIN them for specific queries, e.g. the products a specific shop carries:
SELECT p.Name
FROM Shop AS s
JOIN Products_in_shop AS pis ON pis.shop_id = s.id
JOIN Product AS p ON pis.product_id = p.id
WHERE s.Name = 'MyShop'

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