Selecting data across mulitple tables in Oracle SQL - sql

I am new to SQL and I am trying to lists all organizations by name in ascending order with the maximum salary across all employees who belong to the organization. I have the Schema Below. Can anyone offer any help? I am also trying to lists all employees by name and if the employee is a manager of at least one organization, provide a row in the results with the name
of each org he/she manages else null.
SELECT Org.name, MAX(Employee.salary) AS "Highest salary"
From Org, Employee
GROUP BY Org.name;
The above code gets me a list of all the Org Names with the global max salary, but I am looking for the max of each Org. I think I may need to use some joins but I am not very familiar.
CREATE TABLE Employee
(
employeeId numeric(9) not null,
name varchar2(100) unique,
salary numeric(9) not null,
CONSTRAINT employeeId_pk PRIMARY KEY (employeeId)
);
CREATE TABLE Org
(
orgId numeric(9) not null,
name varchar2(100) not null unique,
managerId numeric(9) not null,
CONSTRAINT orgId_pk PRIMARY KEY (orgId),
CONSTRAINT managerId_fk FOREIGN KEY (managerId)
REFERENCES Employee(employeeId)
);
CREATE TABLE EmployeeOrg
(
employeeId numeric(9) not null,
orgId numeric(9) not null,
CONSTRAINT employeeId_orgId_pk PRIMARY KEY (employeeId, orgId),
CONSTRAINT employeeId_fk FOREIGN KEY (employeeId)
REFERENCES Employee(employeeId),
CONSTRAINT orgId_fk FOREIGN KEY (orgId)
REFERENCES Org(orgId)
);
INSERT ALL
INTO Employee (employeeId, name, salary) VALUES (123, 'Jim', 123)
INTO Employee (employeeId, name, salary) VALUES (456, 'Bill', 1456)
INTO Employee (employeeId, name, salary) VALUES (789, 'Frank', 456)
INTO Employee (employeeId, name, salary) VALUES (987, 'Sara', 45668)
INTO Employee (employeeId, name, salary) VALUES (654, 'Liz', 4456)
INTO Employee (employeeId, name, salary) VALUES (321, 'Morgan', 4556)
SELECT * FROM dual;
INSERT ALL
INTO Org (orgId, name, managerId) VALUES (1, 'Sales', 123)
INTO Org (orgId, name, managerId) VALUES (2, 'HR', 789)
INTO Org (orgId, name, managerId) VALUES (3, 'E Suite', 987)
INTO Org (orgId, name, managerId) VALUES (4, 'Marketing', 654)
SELECT * FROM dual;
INSERT ALL
INTO EmployeeOrg (employeeId, orgId) VALUES (123, 1)
INTO EmployeeOrg (employeeId, orgId) VALUES (789, 2)
INTO EmployeeOrg (employeeId, orgId) VALUES (987, 3)
INTO EmployeeOrg (employeeId, orgId) VALUES (654, 4)
INTO EmployeeOrg (employeeId, orgId) VALUES (123, 4)
INTO EmployeeOrg (employeeId, orgId) VALUES (456, 1)
INTO EmployeeOrg (employeeId, orgId) VALUES (321, 2)
INTO EmployeeOrg (employeeId, orgId) VALUES (789, 4)
INTO EmployeeOrg (employeeId, orgId) VALUES (456, 2)
SELECT * FROM dual;
EDIT (from OP's comment)
The below code gets me a list of all the Org Names with the global max salary, but I am looking for the max of each Org. I think I may need to use some joins but I am not very familiar.
SELECT Org.name, MAX(Employee.salary) AS "Highest salary"
From Org, Employee
GROUP BY Org.name

select o.orgId, min(o.name) as orgName, max(e.salary) as maxSalary
from Org o
inner join EmployeeOrg eo on eo.orgId = o.orgId
inner join Employee e on e.employeeId = eo.employeeId
group by o.orgId
order by orgName;
select e.name as empName, o.name as orgName
from Employee e left outer join Org o on o.managerId = e.employeeId
order by empName, orgName;

Related

Query to find name of parents with age of youngest child

I have a table as such:
CREATE TABLE people
(
id INTEGER NOT NULL PRIMARY KEY,
motherId INTEGER,
fatherId INTEGER,
name VARCHAR(30) NOT NULL,
age INTEGER NOT NULL,
FOREIGN KEY (motherId) REFERENCES people(id),
FOREIGN KEY (fatherId) REFERENCES people(id)
);
INSERT INTO people(id, motherId, fatherId, name, age)
VALUES (1, NULL, NULL, 'Adam', 50);
INSERT INTO people(id, motherId, fatherId, name, age)
VALUES (2, NULL, NULL, 'Eve', 50);
INSERT INTO people(id, motherId, fatherId, name, age)
VALUES (3, 2, 1, 'Cain', 30);
INSERT INTO people(id, motherId, fatherId, name, age)
VALUES (4, 2, 1, 'Seth', 20);
I would like to write a query and get the name of the parents and the age of their youngest children. Not sure how to go about with this problem.
Expected output:
-- Expected output (in any order):
-- name age
-- ----------------------------
-- Adam 20
-- Eve 20
SELECT P1.name, P2.name, T.minAge
FROM (SELECT P.motherId, P.fatherId, MIN(AGE) AS minAge
FROM people P
GROUP BY P.motherId, P.fatherId) AS T JOIN people P1 ON T.motherId=P1.id
JOIN people P2 ON T.fatherId=P2.id
db<>fiddle

Oracle Hierarchical queries with views and joins

I have a table setup like this:
create table DEP
(
depid NUMBER,
name VARCHAR2(200),
manager NUMBER
);
create table EMP
(
empid NUMBER,
depid NUMBER,
name VARCHAR2(200),
role VARCHAR2(200),
salary NUMBER,
manager NUMBER
);
insert into dep (DEPID, NAME, MANAGER)
values (1, 'IT', 2);
insert into dep (DEPID, NAME, MANAGER)
values (2, 'ACCOUNTING', 4);
insert into dep (DEPID, NAME, MANAGER)
values (3, 'MARKETING', 5);
insert into emp (EMPID, DEPID, NAME, ROLE, SALARY, MANAGER)
values (1, 1, 'KEVIN', 'PROGRAMMER', 20000, 2);
insert into emp (EMPID, DEPID, NAME, ROLE, SALARY, MANAGER)
values (2, 1, 'LOUIS', 'ANALYST', 30000, null);
insert into emp (EMPID, DEPID, NAME, ROLE, SALARY, MANAGER)
values (3, 2, 'RACHEL', 'CASHER', 15000, 4);
insert into emp (EMPID, DEPID, NAME, ROLE, SALARY, MANAGER)
values (4, 2, 'JOHN', 'ECONOMIST', 50000, null);
insert into emp (EMPID, DEPID, NAME, ROLE, SALARY, MANAGER)
values (5, 3, 'ERNEST', 'WRITER', 22000, null);
insert into emp (EMPID, DEPID, NAME, ROLE, SALARY, MANAGER)
values (6, 3, 'JACK', 'COMMUNITY MANAGER', 18000, 5);
Then I create these two equivalent views
create or replace view depemp1 as
with v as (
select emp.empid, dep.depid, dep.name depname, emp.name, emp.role, emp.salary,emp.manager
from emp, dep
where emp.depid = dep.depid
)
select v1.empid v1_empid, v1.depid v1_depid, v1.depname v1_depname, v1.name v1_name, v1.role v1_role, v1.salary v1_salary,v1.manager v1_manager
,v2.empid v2_empid, v2.depid v2_depid, v2.depname v2_depname, v2.name v2_name, v2.role v2_role, v2.salary v2_salary,v2.manager v2_manager
from v v1 ,v v2
where v1.empid = v2.empid
create or replace view depemp2 as
select emp1.empid v1_empid, dep1.depid v1_depid, dep1.name v1_depname, emp1.name v1_name, emp1.role v1_role, emp1.salary v1_salary,emp1.manager v1_manager
,emp2.empid v2_empid, dep2.depid v2_depid, dep2.name v2_depname, emp2.name v2_name, emp2.role v2_role, emp2.salary v2_salary,emp2.manager v2_manager
from emp emp1, emp emp2, dep dep1, dep dep2
where emp1.depid = dep1.depid and emp2.depid = dep2.depid
and emp2.empid = emp1.empid
If I select from them I can check it.
select * from depemp1;
select * from depemp2;
Now lets consider the next query to depemp1:
select
level,
depemp1.*
from depemp1
connect by prior v1_empid = v1_manager
start with v1_manager is null
The query above gives no result. Nevertheless, the same query to depemp2 (that gives the same rows and data than depemp1) gives 6 rows.
select
level,
depemp2.*
from depemp2
connect by prior v1_empid = v1_manager
start with v1_manager is null
I am using Oracle 10g and I don't understand why is this behaviour. I think this hierarchical query works on the same data output from depemp1 and depemp2 and should give the same result.

Get value from table to use it in insert

I suppose this question was already asked somewhere here, but I have no idea how to name (and look for) it correctly.
The database:
CREATE TABLE department (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(100) NOT NULL UNIQUE
);
CREATE TABLE employee (
id INTEGER PRIMARY KEY AUTOINCREMENT,
department_id INTEGER NOT NULL,
chief_id INTEGER,
name VARCHAR(100) NOT NULL UNIQUE,
salary INTEGER NOT NULL,
FOREIGN KEY (department_id) REFERENCES department (id),
FOREIGN KEY (chief_id) REFERENCES employee (id)
);
INSERT INTO department (name) VALUES ('sales'), ('it'), ('management');
INSERT INTO employee (department_id, chief_id, name, salary) VALUES
(3, NULL, 'Owner', 1000000),
(2, 1, 'Team manager', 9000),
(2, 3, 'Senior dev #1', 7000),
(2, 3, 'Senior dev #2', 7000);
Now in insert I should calculate chief_id on my own, but I'm curious if there is a possibility to get id by name, something like
SELECT id FROM employee WHERE name = 'Owner'
and use this value instead of hardcoded id in insert.
I've tried putting select statement instead of id but that does not work.
I am using SQLite.
You can do it with a subquery as yours, but the data has to be in the table before you can select it. Otherwise the subquery returns null. So you need to break the one INSERT into multiple INSERTs.
INSERT INTO employee (department_id, chief_id, name, salary) VALUES
(3, NULL, 'Owner', 1000000);
INSERT INTO employee (department_id, chief_id, name, salary) VALUES
(2, (SELECT id FROM employee WHERE name = 'Owner'), 'Team manager', 9000);
INSERT INTO employee (department_id, chief_id, name, salary) VALUES
(2, (SELECT id FROM employee WHERE name = 'Team manager'), 'Senior dev #1', 7000),
(2, (SELECT id FROM employee WHERE name = 'Team manager'), 'Senior dev #2', 7000);
But note, that the subquery must return only one row. So the column you're checking in it's WHERE clause must contain unique values. Usually a name is not unique, there are a lot of John Smith. Usually the ID is the unique identifier. So in a general inserting the ID directly is the right approach.

joining three tables together using Inner Joins

Using Table aliases, list the first name, last name and start date of students enrolled on the java fundamentals module:
I am having some trouble when running the query below.
SELECT stu.StudFName, stu.StudLName, enrol.StartDate
From Student stu
INNER JOIN Enrolment enrol
ON stu.StudID = enrol.StudID
INNER JOIN Module mod
ON enrol.ModCode = mod.ModCode
WHERE mod.ModName = 'Java Fundamentals'
Structure:
CREATE TABLE Student
(StudID INTEGER PRIMARY KEY,
StudFName VARCHAR(10) NOT NULL,
StudLName VARCHAR(10) NOT NULL,
DoB DATE NOT NULL,
Sex CHAR(1) NOT NULL CHECK (Sex IN ('M', 'F')),
Email VARCHAR(30) UNIQUE);
CREATE TABLE Staff
(StaffID INTEGER PRIMARY KEY,
Title VARCHAR(4) CHECK (Title IN ('Prof', 'Dr', 'Mr', 'Mrs', 'Miss')),
StaffFName VARCHAR(10) NOT NULL,
StaffLName VARCHAR(10) NOT NULL,
Email VARCHAR(30) UNIQUE,
Department VARCHAR(25) DEFAULT 'Not Assigned',
Extension INTEGER CHECK (Extension BETWEEN 0001 AND 9999));
CREATE TABLE Module
(ModCode CHAR(4) PRIMARY KEY,
ModName VARCHAR(25) NOT NULL,
ModCredits INTEGER NOT NULL CHECK (ModCredits IN (15, 30, 45, 60)),
ModLevel CHAR(3) NOT NULL CHECK (ModLevel IN ('UG1', 'UG2', 'UG3', 'MSc')),
ModLeader INTEGER NOT NULL,
Foreign Key (ModLeader) REFERENCES Staff (StaffID));
CREATE TABLE Enrolment
(ModCode CHAR(4) NOT NULL,
StudID INTEGER NOT NULL,
StartDate DATE NOT NULL,
PRIMARY KEY (ModCode, StudID),
Foreign Key (StudID) REFERENCES Student (StudID),
Foreign Key (ModCode) REFERENCES Module (ModCode));
The answer is... there is no trouble with your query.
It works just fine.
Check here
INSERT INTO Student (StudID, StudFName, StudLName, DoB, Sex, Email) VALUES
(1, 'Jack', 'Black', TO_DATE('2015/01/01', 'yyyy/mm/dd'), 'M', 'jack#email.com');
INSERT INTO Student (StudID, StudFName, StudLName, DoB, Sex, Email) VALUES
(2, 'Andrew', 'Wiggin', TO_DATE('2015/01/01', 'yyyy/mm/dd'), 'M', 'andrew#email.com');
INSERT INTO Student (StudID, StudFName, StudLName, DoB, Sex, Email) VALUES
(3, 'Bob', 'Marley', TO_DATE('2015/01/01', 'yyyy/mm/dd'), 'M', 'bob#email.com');
INSERT INTO Staff (StaffID, Title, StaffFName, StaffLName, Email, Extension) VALUES
(1, 'Prof', 'Joe', 'Smith', 'stuff#emal.com', 0001);
INSERT INTO Module (ModCode, ModName, ModCredits, ModLevel, ModLeader) VALUES
(1, 'Java Fundamentals', 30, 'UG1', 1);
INSERT INTO Module (ModCode, ModName, ModCredits, ModLevel, ModLeader) VALUES
(2, 'C# Fundamentals', 15, 'UG2', 1);
INSERT INTO Enrolment (ModCode, StudID, StartDate) VALUES
(1, 1, TO_DATE('2015/01/01', 'yyyy/mm/dd'));
INSERT INTO Enrolment (ModCode, StudID, StartDate) VALUES
(1, 2, TO_DATE('2015/01/02', 'yyyy/mm/dd'));
INSERT INTO Enrolment (ModCode, StudID, StartDate) VALUES
(2, 3, TO_DATE('2015/01/03', 'yyyy/mm/dd'));
-------------------------------------------------------------
SELECT stu.StudFName, stu.StudLName, enrol.StartDate
From Student stu
INNER JOIN Enrolment enrol ON stu.StudID = enrol.StudID
INNER JOIN Module mod ON enrol.ModCode = mod.ModCode
WHERE mod.ModName = 'Java Fundamentals'
Result
STUDFNAME STUDLNAME STARTDATE
----------------------------------------
Jack Black January, 01 2015
Andrew Wiggin January, 02 2015

Get all parent's Id including the root's Id with CTE

From EmployeeId 8 I want to get all his parents EmployeeId's which are these EmployeeId's 7,5,3,2,1
CREATE TABLE EmployeeTree(
EmployeeId int,
EmployeeName nvarchar(100),
EmployeeType nvarchar(40),
EmployeeParentId int
)
INSERT INTO EmployeeTree (EmployeeId, EmployeeName, EmployeeType, EmployeeParentId)
VALUES (1, 'Mickey Mouse', 'CEO', NULL)
INSERT INTO EmployeeTree (EmployeeId, EmployeeName, EmployeeType, EmployeeParentId)
VALUES (2, 'Minnie Mouse', 'President', 1)
INSERT INTO EmployeeTree (EmployeeId, EmployeeName, EmployeeType, EmployeeParentId)
VALUES (3, 'Donald Duck', 'Division Head', 2)
INSERT INTO EmployeeTree (EmployeeId, EmployeeName, EmployeeType, EmployeeParentId)
VALUES (4, 'Daffy Duck', 'Division Head', 2)
INSERT INTO EmployeeTree (EmployeeId, EmployeeName, EmployeeType, EmployeeParentId)
VALUES (5, 'Scrooge McDuck', 'Department Head', 3)
INSERT INTO EmployeeTree (EmployeeId, EmployeeName, EmployeeType, EmployeeParentId)
VALUES (6, 'Huey McDuck', 'Team Lead', 5)
INSERT INTO EmployeeTree (EmployeeId, EmployeeName, EmployeeType, EmployeeParentId)
VALUES (7, 'Dewey McDuck', 'Team Lead', 5)
INSERT INTO EmployeeTree (EmployeeId, EmployeeName, EmployeeType, EmployeeParentId)
VALUES (8, 'Louie McDuck', 'Team Member', 7)
With this code I run into recursive problems:
DECLARE #EmployeeId INT
SET #EmployeeId = 8;
WITH x(Id) AS (SELECT #EmployeeId UNION ALL SELECT dbo.EmployeeTree.EmployeeId
FROM dbo.EmployeeTree INNER JOIN x ON EmployeeTree.EmployeeId = x.Id )
Select * FROM x JOIN dbo.EmployeeTree as e ON e.EmployeeParentId = x.Id
What do I have to correct in my CTE that I get all parent employee ids for the employeeId 8 ?
You can achieve that using this CTE query. Note that the anchor query also selects from your source table and both employee ID and parent ID are returned in each iteration so that the parent can be joined each time.
DECLARE #EmployeeId INT
SET #EmployeeId = 8;
WITH x AS (
SELECT EmployeeId, EmployeeParentId
FROM dbo.EmployeeTree
WHERE EmployeeId = #EmployeeId
UNION ALL
SELECT dbo.EmployeeTree.EmployeeId, dbo.EmployeeTree.EmployeeParentId
FROM dbo.EmployeeTree
INNER JOIN x ON EmployeeTree.EmployeeId = x.EmployeeParentId )
Select EmployeeId FROM x
where EmployeeId <> #EmployeeId