Oracle. Multiplying a sum() with a subquery. - sql

Why does this query not work? I get the error "not a single-group group function".
select sum(stock.stkprice) * (select nation.exchrate from nation where nation.natcode = 'UK') from stock;
Is it because the subquery might return multiple values? It's using the primary key, natcode, so it should only return a single exchange rate. Below are the tables.
create table nation
(natcode char(3) not null,
natname char(20),
exchrate number(9,5),
constraint pk_nation primary key (natcode));
create table stock
(stkcode char(3) not null,
stkfirm char(20),
stkprice number(6,2),
stkqty number(8),
stkdiv number(5,2),
stkpe number(5),
natcode char(3),
constraint pk_stock primary key (stkcode),
constraint fk_hasnation foreign key (natcode) references nation(natcode));

Join the tables as the columns to be used for aggregation come from different tables. The query in question is incorrect syntactically.
select sum(stock.stkprice * nation.exchrate)
from nation
join stock on stock.natcode=nation.natcode
where nation.natcode = 'UK'

Related

For each ‘CptS’ course, find the percentage of the students who failed the course. Assume a passing grade is 2 or above

CREATE TABLE Course (
courseno VARCHAR(7),
credits INTEGER NOT NULL,
enroll_limit INTEGER,
classroom VARCHAR(10),
PRIMARY KEY(courseNo), );
CREATE TABLE Student (
sID CHAR(8),
sName VARCHAR(30),
major VARCHAR(10),
trackcode VARCHAR(10),
PRIMARY KEY(sID),
FOREIGN KEY (major,trackcode) REFERENCES Tracks(major,trackcode) );
CREATE TABLE Enroll (
courseno VARCHAR(7),
sID CHAR(8),
grade FLOAT NOT NULL,
PRIMARY KEY (courseNo, sID),
FOREIGN KEY (courseNo) REFERENCES Course(courseNo),
FOREIGN KEY (sID) REFERENCES Student(sID) );
So far I've been able to create two seperate queries, one that counts the number of people who failes. And the other counts the number of people who passed. I'm having trouble combining these to produce the number of people passed / number of people failed. For each course.
SELECT course.courseno, COUNT(*) FROM course inner join enroll on enroll.courseno = course.courseno
WHERE course.courseno LIKE 'CptS%' and enroll.grade < 2
GROUP BY course.courseno;
SELECT course.courseno, COUNT(*) FROM course inner join enroll on enroll.courseno = course.courseno
WHERE course.courseno LIKE 'CptS%' and enroll.grade > 2
GROUP BY course.courseno;
The end result should look something like
courseno passrate
CptS451 100
CptS323 100
CptS423 66
You can do a conditional average for this:
select
courseno,
avg(case when grade > 2 then 100.0 else 0 end) passrate
from enroll
where courseno like 'CptS%'

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)

How do I find out the Top N diseases according to the cost of their treatment?

This is what I've tried so far
SELECT DISTINCT
RECORDS.TOTAL_COST, DISEASE.DISEASE_ID
FROM
RECORDS, DISEASE
WHERE
DISEASE.DISEASE_ID = RECORDS.DISEASE_ID
AND TREATMENT.TREATMENT_ID = RECORDS.TREATMENT_ID
GROUP BY
DISEASE.DISEASE_NAME
This is the star schema for the data provided
Treatment table
CREATE TABLE treatment
(
treatment_id NUMBER(6),
treatment_type VARCHAR2(30),
private_cost NUMBER(8,2),
public_cost NUMBER(8,2),
description VARCHAR
)
Create the records fact table
CREATE TABLE records
(
patient_id NUMBER(6),
doctor_id NUMBER(6),
disease_id NUMBER(6),
treatment_id NUMBER(6),
time_id DATE,
side_effects NUMBER(1),
effectivness NUMBER(1),
total_cost NUMBER(8,2)
);
Create foreign keys to all dimensional tables
ALTER TABLE records
ADD ( CONSTRAINT records_patients_fk FOREIGN KEY (patient_id) REFERENCES patients,
CONSTRAINT records_doctors_fk FOREIGN KEY (doctor_id) REFERENCES doctors,
CONSTRAINT records_disease_fk FOREIGN KEY (disease_id) REFERENCES disease,
CONSTRAINT records_treatment_fk FOREIGN KEY (treatment_id) REFERENCES treatment,
CONSTRAINT records_times_fk FOREIGN KEY (time_id) REFERENCES times);
CREATE TABLE disease
(
disease_id NUMBER(6),
disease_name VARCHAR2(30)
);
Assuming the data returned in the first query is mostly correct aside from wanting only the top N items:
SELECT TOTAL_COST, DISEASE_ID
FROM
(
SELECT DISTINCT RECORDS.TOTAL_COST, DISEASE.DISEASE_ID
FROM RECORDS, DISEASE
WHERE DISEASE.DISEASE_ID=RECORDS.DISEASE_ID AND
TREATMENT.TREATMENT_ID=RECORDS.TREATMENT_ID
GROUP BY DISEASE.DISEASE_NAME
ORDER BY RECORDS.TOTAL_COST DESC
)
WHERE ROWNUM <= 5; -- replace 5 with however many you want.

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.