Count Query Reciepe/Ingredients - sql

basically I've been working on an SQL question which is asking to display each ingredient along with the total number of recipes it's included in. It also must only include the ingredients that occur more than 10 times and descending order of ingredient popularity and ascending order of ingrdesc.
the tables are as followed:
CREATE TABLE Ingredient
(
idI NUMBER constraint pk_Ingredient PRIMARY KEY ,
ingrDesc VARCHAR2(100) constraint nn1Ingredient not null
);
CREATE TABLE Recipe
(
idR NUMBER constraint pk_recipe PRIMARY KEY ,
recipeTitle VARCHAR2(200) constraint nn1Recipe not null,
prepText VARCHAR2(4000),
cuisineType VARCHAR2(50),
mealType VARCHAR2(30) DEFAULT NULL,
CONSTRAINT ch_mealType CHECK (mealType IN ('starter', 'main', 'dessert', null))
);
CREATE TABLE RecpIngr
(
idR NUMBER ,
hidI NUMBER ,
CONSTRAINT pk_RecpIngr PRIMARY KEY (idR, idI),
CONSTRAINT fk1RecpIngr_recipe foreign key(idR) references Recipe,
CONSTRAINT fk2RecpIngr_ingredient foreign key(idI) references Ingredient
)
organization index;
So far I have this query:
SELECT ingrDesc,
COUNT (idR) As num_of_recipes
FROM RespIngr
WHERE num_of_recipes <10
ORDER BY num_of_recipes DES, ingrDes ASC;

Try this:
SELECT ingrDesc,
COUNT (idR) As num_of_recipes
FROM RespIngr
GROUP BY ingrDesc
HAVING COUNT (idR) > 10
ORDER BY num_of_recipes DESC, ingrDesc ASC;

I don't get it. You show a query from table RespIngr but you don't mention such a table. You show a table RecpIngr but that doesn't contain the field ingrDesc.
To get the fields you show, the query must contain a join of the table that contains the recipes and ingredients and the table that contains the description of the ingredients.
with
RCount( IngID, RecipeCount )as(
select hidI, count(*)
from RecpIngr
group by hidI
having count(*) > 10
)
select i.ingrDesc as "Ingredient", rc.RecipeCount as "Number of Recipes"
from Ingredient i
join RCount rc
on rc.IngID = i.idI;

Related

How to join Views with aggregate functions?

My problem:
In #4, I'm having trouble joining two Views because the other has an aggregate function. Same with #5
Question:
Create a view name it as studentDetails, that would should show the student name, enrollment date, total price per unit and subject description of students who are enrolled on the subject Science or History.
Create a view, name it as BiggestPrice, that will show the subject id and highest total price per unit of all the subjects. The view should show only the highest total price per unit that are greater than 1000.
--4.) Create a view name it as studentDetails, that would should show the student name,
-- enrollment date the total price per unit and subject description of students who are
-- enrolled on the subject Science or History.
CREATE VIEW StudentDetails AS
SELECT StudName, EnrollmentDate
--5.) Create a view, name it as BiggestPrice, that will show the subject id and highest total
-- price per unit of all the subjects. The view should show only the highest total price per unit
-- that are greater than 1000.
CREATE VIEW BiggestPrice AS
SELECT SubjId, SUM(Max(Priceperunit)) FROM Student, Subject
GROUP BY Priceperunit
Here is my table:
CREATE TABLE Student(
StudentId char(5) not null,
StudName varchar2(50) not null,
Age NUMBER(3,0),
CONSTRAINT Student_StudentId PRIMARY KEY (StudentId)
);
CREATE table Enrollment(
EnrollmentId varchar2(10) not null,
EnrollmentDate date not null,
StudentId char(5) not null,
SubjId Number(5) not null,
constraint Enrollment_EnrollmentId primary key (EnrollmentId),
constraint Enrollment_StudentId_FK foreign key (StudentId) references Student(StudentId),
constraint Enrollment_SubjId_Fk foreign key (SubjId) references Subject(SubjId)
);
Create table Subject(
SubjId number(5,0) not null,
SubjDescription varchar2(200) not null,
Units number(3,0) not null,
Priceperunit number(9,0) not null,
Constraint Subject_SubjId_PK primary key (SubjId)
);
Since this appears to be a homework question.
You need to use JOINs. Your current query:
CREATE VIEW StudentDetails AS
SELECT StudName, EnrollmentDate
Does not have a FROM clause and the query you have for question 5 uses the legacy comma join syntax with no WHERE filter; this is the same as a CROSS JOIN and will connect every student to every subject and is not what you want.
Don't use the legacy comma join syntax and use ANSI joins and explicitly state the join condition.
SELECT <expression list>
FROM student s
INNER JOIN enrollment e ON ...
INNER JOIN subject j ON ...
Then you can fill in the ... based on the relationships between the tables (typically the primary key of one table = the foreign key of another table).
Then for the <expression list> you need to include the columns asked for in the question: student name and enrolment date and subject name would just be those columns from the appropriate tables; and total price-per-unit (which I assume is actually total-price-per-subject) would be a calculation.
Then for the last part of question 4.
who are enrolled on the subject Science or History.
Add a WHERE filter to only include rows for those subjects.
For question 5, you do not need any JOINS as the question only asks about details in the SUBJECT table.
You need to add a WHERE filter to show "only the highest total price per unit that are greater than 1000". This is a simple multiplication and then you can filter by comparing if it is > 1000.
Then you need to limit the query to return only the row with the "highest total price per unit of all the subjects". From Oracle 12, this would be done with an ORDER BY clause in descending order of total price and then using FETCH FIRST ROW ONLY or FETCH FIRST ROW WITH TIES.
Not sure if i get it fully, but i think its this :
Notes:
Always use Id's to filter records:
where su.SubjId in (1,2)
You can find max record using max() at subquery and join it with main query like this :
where su2.SubjId = su.SubjId
You cannot use alias as filter so you can filter it like:
( su.Units * su.Priceperunit ) > 1000
CREATE VIEW StudentDetails AS
select s.StudName,
e.EnrollmentDate,
su.SubjDescription,
su.Units * su.Priceperunit TotalPrice
from student s
inner join Enrollment e
on e.StudentId = s.StudentId
inner join Subject su
on su.SubjId = e.SubjId
where su.SubjId in (1,2)
CREATE VIEW BiggestPrice AS
select su.SubjId, ( su.Units * su.Priceperunit ) TotalPrice
from Subject su
where ( su.Units * su.Priceperunit ) =
(
select max(su2.Units * su2.Priceperunit)
from Subject su2
where su2.SubjId = su.SubjId
)
and ( su.Units * su.Priceperunit ) > 1000

SQLite GROUP BY lowest price missing results

I've got a SQLite DB that houses basically a list of products and prices.
CREATE TABLE brand_list (
id INTEGER NOT NULL,
brand_name TEXT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE product_list (
id INTEGER NOT NULL,
prod_generic VARCHAR NOT NULL,
prod_pretty VARCHAR NOT NULL,
PRIMARY KEY (id),
UNIQUE (prod_generic)
);
CREATE TABLE qty_list (
id INTEGER NOT NULL,
qty_initial VARCHAR NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE vendor_list (
id INTEGER NOT NULL,
vendor_name TEXT NOT NULL,
vendor_url VARCHAR NOT NULL, url_pretty varchar not null default 1, datacollect varchar not null default 'Y',
PRIMARY KEY (id)
);
CREATE TABLE listing (
id INTEGER NOT NULL,
brand_id INTEGER,
qty_id INTEGER,
vendor_id INTEGER,
prod_id INTEGER,
qty_actual INTEGER,
price INTEGER,
unit_price FLOAT,
timestamp VARCHAR(255),
sale INTEGER DEFAULT 0 NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY(brand_id) REFERENCES brand_list (id),
FOREIGN KEY(prod_id) REFERENCES product_list (id),
FOREIGN KEY(qty_id) REFERENCES qty_list (id),
FOREIGN KEY(vendor_id) REFERENCES vendor_list (id)
I pull a query looking at the listing table with the goal of grabbing the lowest price and listing all of the relevant information for end users (ie brands, products, qty, price, when it was pulled, where it was pulled from).
select qty_initial, qty_actual, price, MIN(unit_price), brand_name, prod_pretty, sale, timestamp, vendor_name from listing left join brand_list on listing.brand_id = brand_list.id left join product_list on listing.prod_id = product_list.id left join vendor_list on listing.vendor_id = vendor_list.id left join qty_list on listing.qty_id = qty_list.id group by prod_pretty order by brand_name, prod_pretty
What I'm seeing is that most of the data is showing up but not all of the data is showing up. And it doesn't seem consistent - but one brand might show seven out of eight entries, another brand might have everything.
The interesting part is that if I add a WHERE clause just prior to the group by and specify a brand that I know is missing entries in the original output, I'll get all of the expected output for that brand.
This isn't my world - I'm just hacking something together for my own fun. I'm certain I'm missing something fundamental here and it's likely around the GROUP BY. Any direction would be great - even a way to rethink how I'm doing this to get to where I want to be in a simpler manner.
Your query is malformed -- although SQLite does accept it. The GROUP BY columns are inconsistent with the SELECT list.
Instead, use window functions:
select qty_initial, qty_actual, price, unit_price, brand_name, prod_pretty, sale, timestamp, vendor_name
from (select qty_initial, qty_actual, price, unit_price, brand_name, prod_pretty, sale, timestamp, vendor_name,
row_number() over (partition by prod_pretty order by unit_price) as seqnum
from listing left join
brand_list
on listing.brand_id = brand_list.id left join
product_list
on listing.prod_id = product_list.id left join
vendor_list
on listing.vendor_id = vendor_list.id left join
qty_list
on listing.qty_id = qty_list.id
group by prod_pretty
) p
where seqnum = 1
order by brand_name, prod_pretty

Show the names of customers that have accounts SQL Query Oracle 10G

create table customer
(cust_id integer not null,
cust_name char(20) not null ,
cust_address varchar2(200) ,
emp_id integer not null,
constraint pk_customer primary key(cust_id)
);
create table account
(account_number integer not null,
account_balance number(8,2) not null,
constraint pk_acount primary key(account_number)
);
create table has
(cust_id integer not null,
account_number integer not null,
constraint pk_has
primary key(cust_id, account_number) )
alter table has
add constraint fk_account_has foreign key(account_number)
references account(account_number);
alter table has
add constraint fk_customer_has foreign key(cust_id)
references customer(cust_id);
Q1 Show the names of customers that have accounts
Q2 Show the customer names with the names of the employees they deal with**
Q1 is a simple lookup of the cust_id in junction table has:
select c.cust_name
from customer c
where exists (select 1 from has h where h.cust_id = c.cust_id)
This phrases as: select the customers that have at least one entry in the has table.
When it comes to Q2: your data structures show no sign of employees (all we have is customers and accounts), so this cannot be answered based on the information that you provided. You might want to ask a new question for this, providing sample data for the involved tables, along with desired results and you current attempt at solving the problem.

PostgreSQL SELECT JOIN

I have a problem with making a proper SELECT for my exercise:
There are two tables that I have created:
1. Customer
2. Order
ad. 1
CREATE TABLE public."Customer"
(
id integer NOT NULL DEFAULT nextval('"Customer_id_seq"'::regclass),
name text NOT NULL,
surname text NOT NULL,
address text NOT NULL,
email text NOT NULL,
password text NOT NULL,
CONSTRAINT "Customer_pkey" PRIMARY KEY (id),
CONSTRAINT "Customer_email_key" UNIQUE (email)
)
ad.2
CREATE TABLE public."Order"
(
id integer NOT NULL DEFAULT nextval('"Order_id_seq"'::regclass),
customer_id integer NOT NULL,
item_list text,
order_date date,
execution_date date,
done boolean DEFAULT false,
confirm boolean DEFAULT false,
paid boolean DEFAULT false,
CONSTRAINT "Order_pkey" PRIMARY KEY (id),
CONSTRAINT "Order_customer_id_fkey" FOREIGN KEY (customer_id)
REFERENCES public."Customer" (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
Please do not mind how columns properties were set.
The problem I have is following:
How to make a SELECT query which will give me as a result ids and emails of customers who have ordered something after '2017-09-15'
I suppose that this should go with JOIN but none of the queries I tried have worked :/.
Thanks!
You should post the queries that you tried, but in the meantime try this. It's a simple join :
SELECT DISTINCT id
, email
FROM public."Customer" c
JOIN public."Order" o
ON c.id = o.customer_id
WHERE order_date > '2017-09-15'
In table "Order" you just need to add current constraint for customer id:
customer_id integer REFERENCES Customer (id)
for more information check this page:
https://www.postgresql.org/docs/9.2/static/ddl-constraints.html
So, the query should be like this:
SELECT id, email
FROM Customer
INNER JOIN Order
ON (Order.customer_id = Customer.id)
WHERE order_date >= '2017-09-15'
Also, the useful docs you can check: https://www.postgresql.org/docs/current/static/tutorial-join.html

SQLite, aggregation query as where clause

Given the schema:
CREATE TABLE Student (
studentID INT PRIMARY KEY NOT NULL,
studentName TEXT NOT NULL,
major TEXT,
class TEXT CHECK (class IN ("Freshman", "Sophomore", "Junior", "Senior")),
gpa FLOAT CHECK (gpa IS NULL OR (gpa >= 0 AND gpa <= 4)),
FOREIGN KEY (major) REFERENCES Dept(deptID) ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TABLE Dept (
deptID TEXT PRIMARY KEY NOT NULL CHECK (LENGTH(deptID) <= 4),
NAME TEXT NOT NULL UNIQUE,
building TEXT
);
CREATE TABLE Course (
courseNum INT NOT NULL,
deptID TEXT NOT NULL,
courseName TEXT NOT NULL,
location TEXT,
meetDay TEXT NOT NULL CHECK (meetDay IN ("MW", "TR", "F")),
meetTime INT NOT NULL CHECK (meetTime >= '07:00' AND meetTime <= '17:00'),
PRIMARY KEY (courseNum, deptID),
FOREIGN KEY (deptID) REFERENCES Dept(deptID) ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TABLE Enroll (
courseNum INT NOT NULL,
deptID TEXT NOT NULL,
studentID INT NOT NULL,
PRIMARY KEY (courseNum, deptID, studentID),
FOREIGN KEY (courseNum, deptID) REFERENCES Course ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (studentID) REFERENCES Student(studentID) ON UPDATE CASCADE ON DELETE CASCADE
);
I'm attempting to find the names, IDs, and the number of courses they are taking, for the students who are taking the highest number of courses. The sELECT to retrieve the names and IDs is simple enough, however I'm having trouble figuring out how to select the number of courses each student is taking, and then find the max of that and use it as a WHERE clause.
This is what I have so far:
SELECT Student.studentName, Student.studentID, COUNT(*) AS count
FROM Enroll
INNER JOIN Student ON Enroll.studentID=Student.studentID
GROUP BY Enroll.studentID
So first you get count of all the enrolled classes per student
SELECT COUNT() AS num
FROM Enroll
GROUP BY studentID
You can then check that against your existing query using HAVING to get your final query.
SELECT Student.studentName,Student.studentID,COUNT(*) AS count
FROM Enroll
INNER JOIN Student ON Enroll.studentID=Student.studentID
GROUP BY Enroll.studentID
HAVING COUNT()=(SELECT COUNT() AS num FROM Enroll GROUP BY studentID);
So to recap this basically gets the number which represents the highest number of enrollments for any student, then gets all students where that number is their count of enrollments, thus all students which have the highest, or equal highest number of enrollments.
We use HAVING because it is applied after the GROUP BY, meaning you can't use aggregate functions such as COUNT() in a WHERE clause.