PostgreSQL SELECT JOIN - sql

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

Related

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.

missing right parantjesis, missing expression, error on subquery

My database is for a rental centre with music CDs and videotapes.
create table cds (
id_cd varchar2(5) pk_cduri primary key,
artists varchar2(100) not null,
genre varchar2(20) not null,
release date not null,
constraint pk_cds primary key(id_cd)
);
create table replenishment(
id_ap varchar2(5) constraint pk_aprovizionari primary key,
id_cd varchar2(5),
quantity_cd number(5,2) default 0,
price_cd number(5,2) default 0,
id_cv varchar2(5),
cquantity_cv number(5,2) default 0,
price_cv number(5,2) default 0,
data_rep date default sysdate,
total_cost as (quantity_cd* price_cd+ quantity_cv* price_cv),
constraint fk_ap_cd foreign key (id_cd) references cds,
constraint fk_ap_cv foreign key (id_cv) references videotapes
);
When a customer with id_cust='c1' borrows the cd with id_cd='cd1', then bor_cd=1 and when the customer 'c1' returns the 'cd1' I have to insert value 1 in ret_cd.
create table bor_ret (
id int constraint pk_bor_ret primary key,
id_cust varchar2(5) not null,
id_cd varchar2(5),
bor_cd int default 0,
ret_cd int default 0,
id_cv varchar2(5),
bor_cv int default 0,
ret_cv int default 0,
data date default sysdate,
constraint fk_cd_imp foreign key (id_cd) references cds(id_cd),
constraint fk_cv_imp foreign key (id_cv) references videotapes(id_cv),
constraint fk_ab_imp foreign key (id_cust) references customers,
constraint ck_imp_cd_value_flag check (bor_cd in (1,0)),
constraint ck_imp_cv_value_flag check (bor_cv in (1,0)),
constraint ck_ret_cd_value_flag check (ret_cd in (1,0)),
constraint ck_ret_cv_value_flag check (ret_cv in (1,0))
);
I have to create a trigger (I don't know how to define it, but if someone knows, I will ask a new question to accept it's answer) that sets bor_cd=0 every time after I insert value 1 in ret_cd:
update bor_ret set bor_cd=0 where id_cust=(select id_cust from bor_ret where ret_cd=1);
Then I have to add a computed column to CDS that calculate the quantity of the last cd inserted:
the quantity of 'cd1' from CDS which has the id_cd=cd1 is equal with the quantity supplied from BOR_RET where id_cd=cd1.
So, I want to run this command:
alter table cds add quantity as(
select quantity_cd from replenishment b inner join cds a on a.id_cd=b.id_cd where b.id_cd=
(select id_cd from cds where rownum=1 order by id_cd desc) -
(select count(id_cd) from bor_ret d inner join cds c on c.id_cd=d.id_cd where d.id_cd=
(select id_cd from cds where rownum=1 order by id_cd desc) and d.bor_cd=1));
and I get this error: "missing expression".
If I Run only the query: select quantity_cd... I get the error:
"ERROR at line 2: ORA-00907: missing right paranthesis"
Or, better, how can I add this column as differences of:
select quantity_cd from replenishment where id_cd=(select max(id_cd) from cds) as A
select count(id_cd) from bor_ret where id_cd=(select max(id_cd) from cds) and bor_cd=1 as B
quantity = A-B;
This thread is for solving the problem with computed column, but if someone can explain me how to create the trigger too I will open a new thread for it.
Thank you guys in advance.
Please note 2nd right parenthesis in the last but one line.
select quantity_cd
from replenishment b
inner join cds a on a.id_cd=b.id_cd
where b.id_cd=
(select id_cd from cds where rownum=1 order by id_cd desc) -
(select count(id_cd) from bor_ret d inner join cds c on c.id_cd=d.id_cd where d.id_cd= (select id_cd from cds where rownum=1 order by id_cd desc)) /* <------ ===*/
and d.bor_cd=1)

Count Query Reciepe/Ingredients

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;

How to take the max value for every element in SQL

CREATE TABLE Department(
DNumber integer NOT NULL PRIMARY KEY);
CREATE TABLE Patient(
PID integer NOT NULL PRIMARY KEY,
P_DNumber integer NOT NULL REFERENCES Department (DNumber)
);
CREATE TABLE Appointment(
AppNumber integer NOT NULL PRIMARY KEY,
AppDate date NOT NULL,
App_DNumber integer NOT NULL REFERENCES Department (DNumber)
);
CREATE TABLE Attend(
A_PID integer NOT NULL REFERENCES Patient (PID),
A_AppNumber integer NOT NULL REFERENCES Appointment(AppNumber)
);
HEllo, I have these tables and I want to find for each PID the last Date he attended an appointment. I tried with joins but nothing worked. I am using Postgres. Does anyone have an idea about it?
Thank you very much
Give this a try, joining through Attend and Appointment.
SELECT
Patient.PID,
MAX(Appointment.AppDate) AS lastAttended
FROM
Patient
LEFT JOIN Attend ON Patient.PID = Attend.A_PID
JOIN Appointment ON Appointment.AppNumber = Attend.A_AppNumber
GROUP BY Patient.PID
For patients attending 2+ appointments per month you need COUNT() inside a HAVING clause.
SELECT
Patient.PID,
COUNT(Attend.A_AppNumber) AS numAppts
FROM
Patient
LEFT JOIN Attend ON Patient.PID = Attend.A_PID
GROUP BY Patient.PID
HAVING COUNT(Attend.A_AppNumber) >= 2