1. 10 Facit
SQL frågor del 1
1. Lista hela innehållet i tabellen EMPLOYEES
SELECT * FROM employees;
Kommentar:
Det är ok att använda * när man skriver ad hoc frågor. När man programmerar så ska man
alltid ange kolumnnamnen specifikt. Det händer att kolumner byter ordning. Det är
dessutom svårare att ta bort kolumner som inte används då det inte syns i SQL-satsen.
2. Hur många tecken får du spara kolumnen STREET_ADDRESS i tabellen
LOCATIONS?
DESC locations;
Ger resultatet:
COLUMN_NAME NULLABL
E
DATA_TYP
E
DATA_
LENGTH
DATA_
PRECISION
DATA_
SCALE
LOCATION_ID N NUMBER 4 4 0
STREET_ADDRESS Y VARCHAR2 40
POSTAL_CODE Y VARCHAR2 12
CITY N VARCHAR2 30
STATE_PROVINCE Y VARCHAR2 25
COUNTRY_ID Y CHAR 2
Värdet i data_length för street_address är 40.
Kommentar:
DESC är en förkortning av DESCRIBE vilket också fungerar.
3. Gör en projektion: Lista efternamn (LAST_NAME), lön (SALARY) och
avdelningsnummer (DEPARTMENT_ID) från tabellen EMPLOYEES.
SELECT last_name, salary, department_id
FROM employees;
2. 4 Gör en restriktion. Visa all information för alla anställda som heter John i förnamn.
SELECT *
FROM employees
WHERE first_name ='John';
Resultat
EMPLOYEE_
ID
FIRST_
NAME
LAST_
NAME
EMAIL PHONE_
NUMBER
HIRE_
DATE
JOB_ID
110 John Chen JCHEN 515.124.4269 1997-09-28 FI_ACCOUNT
139 John Seo JSEO 650.121.2019 1998-02-12 ST_CLERK
145 John Russell JRUSSEL 011.44.1344.429
268
1996-10-01 SA_MAN
Kommentar:
Alla kolumner visas inte.
5 Lista JOB_TITLE, MIN_SALARY, MAX_SALARY för alla jobb som minst har
MIN_SALARY på 7000. Sätt följande kolumnalias: Jobb titel, Max lön samt Min lön.
SELECT job_title AS "Jobb titel",
max_salary "Max lön",
min_salary AS"Min lön"
FROM jobs
WHERE min_salary >= 7000;
Resultat
Jobb titel Max lön Min lön
President 40000 20000
Administration Vice President 30000 15000
Finance Manager 16000 8200
Accounting Manager 16000 8200
Sales Manager 20000 10000
Purchasing Manager 15000 8000
Marketing Manager 15000 9000
Kommentar:
Om aliaset har ett mellanslag i sig så måste det skrivas inom ””. AS behöver inte skrivas
ut.
6 Visa alla uppgifter om de anställda på avdelning 10 och 20.
SELECT *
FROM employees
WHERE department_id IN (10, 20);
3. 7 Visa all information om anställda vars efternamn börjar på Ka
SELECT *
FROM employees
WHERE last_name like 'Ka%'
EMPLOYEE_
ID
FIRST_
NAME
LAST_
NAME
EMAIL PHONE_
NUMBER
HIRE_
DATE
JOB_ID SALARY
122 Payam Kaufling PKAUFLIN 650.123.3234 1995-05-
01
ST_MAN 7900
Alla kolumner visas inte.
8 Visa alla anställa som har en lön mellan 7700 och 11200
SELECT first_name,
last_name,
salary
FROM employees
WHERE salary BETWEEN 7700 AND 11200
Eller
SELECT first_name,
last_name,
salary
FROM employees
WHERE salary >= 7700
AND salary <= 11200
FIRST_NAME LAST_NAM
E
SALARY
Alexander Hunold 9000
Daniel Faviet 9000
John Chen 8200
Ismael Sciarra 7700
Jose Manuel Urman 7800
Den Raphaely 11000
Matthew Weiss 8000
Adam Fripp 8200
Payam Kaufling 7900
Gerald Cambrault 11000
Eleni Zlotkey 10500
Peter Tucker 10000
David Bernstein 9500
Alla 29 rader visas inte.
Kommentar:
Det är valfritt att använda båda varianterna. Databashanteraren skriver om BETWEEN …
AND … varianten till >= <= så det är samma uttryck om körs.
4. 9 Som ovan men visa enbart de personer som inte får bonus.
SELECT first_name,
last_name,
salary,
commission_pct
FROM employees
WHERE salary >= 7700
AND salary <= 11200
AND commission_pct IS NULL
Resultat
FIRST_NA
ME
LAST_NA
ME
SALAR
Y
COMMIS
SION_PC
T
Alexander Hunold 9000
Daniel Faviet 9000
John Chen 8200
Ismael Sciarra 7700
Jose Manuel Urman 7800
Den Raphaely 11000
Matthew Weiss 8000
Adam Fripp 8200
Payam Kaufling 7900
Hermann Baer 10000
William Gietz 8300
10 Visa alla personer som har ett efternamn som slutar på s och ett förnamn som börjar
på S.
SELECT first_name,
last_name
FROM employees
WHERE last_name LIKE '%s'
AND first_name LIKE 'S%'
FIRST_NAME LAST_NAME
Sigal Tobias
Stephen Stiles
Susan Marvis
Shelley Higgens
5. 11 Samma som ovan men visa även de personer som har r som andra bokstav i
förnamnet samt ett efternamn som slutar på t. Båda villkoren ska vara uppfyllda.
SELECT first_name,
last_name
FROM employees
WHERE (last_name like '%s' AND first_name like 'S%')
OR (first_name like '_r%' AND last_name like '%t')
FIRST_NAME LAST_NAME
Bruce Ernst
Sigal Tobias
Stephen Stiles
Britney Everett
Susan Marvis
Shelley Higgens
12 Som ovan men endast alla som har ett JOB_ID som avslutas med CLERK
SELECT first_name,
last_name,
job_id
FROM employees
WHERE ((last_name like '%s' AND first_name like 'S%')
OR (first_name like '_r%' AND last_name like '%t'))
AND job_id like '%CLERK'
Resultat
FIRST_NAME LAST_NAM
E
JOB_ID
Sigal Tobias PU_CLERK
Stephen Stiles ST_CLERK
Britney Everett SH_CLERK
6. 13 Vilka personer anställdes före 1993-01-01
SELECT first_name,
last_name,
hire_date
FROM employees
WHERE hire_Date < '1993-01-01'
Resultat
FIRST_NAME LAST_NAM
E
HIRE_DATE
Steven King 1987-06-17
Neena Kochhar 1989-09-21
Alexander Hunold 1990-01-03
Bruce Ernst 1991-05-21
Jennifer Whalen 1987-09-17
14 Visa alla anställa som anställdes mellan dagens datum och 1996-11-29
Frågan tolkas på olika sätt. Här är ett svar.
SELECT first_name,
last_name,
hire_date
FROM employees
WHERE hire_Date >'1996-11-29'
7. 15 Visa tabellnamn och kolumnnamn för alla kolumner som du inte får lägga in NULL
Här gäller det att hitta rätt i data dictionary.
SELECT table_name, column_name, nullable
FROM user_tab_columns
WHERE nullable = 'N'
TABLE_NAME COLUMN_NAME NULLABLE
COUNTRIES COUNTRY_ID N
DEPARTMENTS DEPARTMENT_ID N
DEPARTMENTS DEPARTMENT_NAM
E
N
EMPLOYEES EMPLOYEE_ID N
EMPLOYEES LAST_NAME N
EMPLOYEES EMAIL N
EMPLOYEES HIRE_DATE N
EMPLOYEES JOB_ID N
EMPLOYEES SALARY N
EMP_DETAILS_VIEW EMPLOYEE_ID N
EMP_DETAILS_VIEW JOB_ID N
EMP_DETAILS_VIEW LAST_NAME N
EMP_DETAILS_VIEW SALARY N
EMP_DETAILS_VIEW DEPARTMENT_NAM
E
N
EMP_DETAILS_VIEW JOB_TITLE N
EMP_DETAILS_VIEW CITY N
JOBS JOB_ID N
JOBS JOB_TITLE N
JOB_HISTORY EMPLOYEE_ID N
JOB_HISTORY START_DATE N
JOB_HISTORY END_DATE N
JOB_HISTORY JOB_ID N
LOCATIONS LOCATION_ID N
LOCATIONS CITY N
LOCATIONS_CHECK_VIEW LOCATION_ID N
LOCATIONS_CHECK_VIEW CITY N
LOCATIONS_SET1 LOCATION_ID N
LOCATIONS_SET1 CITY N
LOCATIONS_SET2 LOCATION_ID N
LOCATIONS_SET2 CITY N
16. Visa all information om anställda sorterat stigande på efternamn och fallande på
anställningsdag.
SELECT last_name, hire_date
FROM employees
ORDER BY last_name, hire_date DESC;
8. 17. Sortera alla anställda fallande på efternamn. Lägg sedan till WHERE rownum
<=10. Vilka poster visas egentligen?
SELECT *
FROM employees
WHERE rownum <= 10
ORDER BY last_name DESC;
18. Vilka index äger du? Lista enbart indexnamnet.
DESC user_indexes;
SELECT index_name
FROM user_indexes
ORDER BY index_name;
19. Lista alla index som används i tabellen employees
SELECT index_name
FROM user_indexes
WHERE table_name = 'EMPLOYEES'
ORDER BY index_name;
20. Visa förnamn och efternamn på alla personer som ligger före ’Kaufling’ i
bokstavsordning. Sortera på efternamn.
SELECT first_name, last_name
FROM employees
WHERE last_name < 'Kaufling'
ORDER BY last_name;
21. Lista tabellnamn och tabellkommentar för alla tabeller du äger.
SELECT table_name, comments
FROM user_tab_comments
ORDER BY table_name;
22. Lista alla kolumner i Departments med kolumnkommentarer.
DESC user_col_comments;
SELECT column_name, comments
FROM user_col_comments
WHERE table_name = 'DEPARTMENTS'
ORDER BY column_name;
9. 24. Räkna ut följande uttryck: 2000*345 +200. Du kan använda en tabell som heter
DUAL.
SELECT 2000 * 345 + 200
FROM DUAL;
10. Funktioner
1. Lista, i ordning efter avdelningsnummer, alla anställdas för- och efternamn samt
lön ökad med 15 %. Ta bort eventuella decimaler.
SELECT department_id, first_name, last_name,
TRUNC (salary * 1.15) salary
FROM employees
ORDER BY department_id;
TRUNC kapar bort eventuella decimaler, ingen avrundning sker. Det finns funktioner
som hanterar avrundning (bla ROUND).
2. Visa för- och efternamn samt anställningsdag för alla anställda.
Anställningsdagen ska ha följande formatmall: ’Dy Month year’
SELECT first_name, last_name,
TO_CHAR (hire_date, 'Dy Month year') AS "Hire Date"
FROM employees;
En Oracle databas sparar alltid datum i sekund precision i date datatypen.
3. Som ovan men förnamnet och efternamnet ska enbart visas med små bokstäver.
SELECT LOWER (first_name), LOWER (last_name),
TO_CHAR (hire_date, 'Dy Month year') AS "Hire Date"
FROM employees;
4. Som ovan men den anställdes förnamn och efternamn ska slås ihop och visas i en
kolumn med Namn som alias.
SELECT LOWER (first_name) || ' ' || LOWER (last_name) AS namn,
TO_CHAR (hire_date, 'Dy Month year') AS "Hire Date"
FROM employees
5. Visa förnamn, efternamn och commision_pct för alla anställda. Om
commision_pct är NULL ska ’0’ visas.
SELECT first_name, last_name,
NVL (commission_pct, 0) AS commission_pct
FROM employees;
11. 6. Lista alla anställdas namn, anställningsdatum och anställningstid för alla
anställda. Anställningstiden ska avrundas till hela år.
SELECT first_name, last_name, hire_date,
ROUND (MONTHS_BETWEEN (SYSDATE, hire_date) / 12) AS
"Anställningsår"
FROM employees;
7. Vem har lägst lön?
Ni har ännu inte lärt er hur man ska få ut ett svar med en fråga. Ett alternativ är att
söka ut den minsta lönen först MIN(salary) och använda svaret i en annan
fråga.
Med en subfråga ser svaret ut:
SELECT first_name, last_name
FROM employees
WHERE salary = (SELECT MIN (salary)
FROM employees)
Först utförs subfrågan om att få ut MIN(salary) svaret används sedan i
huvudfrågan.
8. Visa förnamn, efternamn och manager_id för alla anställda. Om manager_id är
NULL ska ’Företagets VD’ visas.
SELECT first_name, last_name,
NVL (TO_CHAR (manager_id), 'Företagets VD')
FROM employees;
9. Hur många rader innehåller tabellen Departments?
SELECT COUNT (*)
FROM departments;
Kommentar:
COUNT(*) och COUNT(1) utför exakt samma sökning i databasen. Det är ingen
prestandaskillnad.
10. Hur många personer har bonus?
SELECT COUNT (*)
FROM employees
WHERE commission_pct IS NOT NULL;
11. Hur många chefer finns det?
SELECT COUNT (DISTINCT (manager_id))
FROM employees;
12. 12. Hur många har en årslön över 100000?
SELECT COUNT (*)
FROM employees
WHERE salary * 12 > 100000
Kommentar:
Av prestandaskäl ska man faktiskt inte skriva som ovan. Det är dock det normala
sättet. Det är betydligt bättre att skriva salary > (1000000/12). Det beror på att om det
finns ett index på salary kan databasen inte använda det i det första alternativet.
13. Vilka olika typer av jobb (job_id) finns det?
SELECT DISTINCT (job_id)
FROM employees;
eller
SELECT job_id
FROM employees
GROUP BY job_id;
14. Lista alla typer av jobb (job_id) samt max- och minlön för respektive jobb.
Sortera i bokstavsordning efter job_id.
SELECT job_id, MAX (salary) MAX, MIN (salary) MIN
FROM employees
GROUP BY job_id;
Kommentar:
Alla kolumner som inte har en grupperingsfunktion måste stå med I GROUP BY
uttrycket.
15. Lista alla avdelningar där medelinkomsten överstiger 5000. Steven King ska inte
räknas med
SELECT department_id, AVG (salary)
FROM employees
WHERE (first_name != 'Steven' AND last_name != 'King')
GROUP BY department_id
HAVING AVG (salary) > 5000
16. Lista alla avdelningar där medelinkomsten överstiger 8000.
SELECT department_id, AVG (salary)
FROM employees
GROUP BY department_id
HAVING AVG (salary) > 8000
13. 17. Gå igenom hur CASE och DECODE funktionerna fungerar.
Lista alla anställdas för och efternamn, lön samt följande:
Om lönen är <3000 Ska det stå Lågavlönad
Om lönen är <10000 Ska det stå Medelavlönad
Om lönen är >10000 Ska det stå Högavlönad
Använd både CASE och DECODE.
SELECT last_name, first_name,
(CASE
WHEN salary < 3000
THEN 'Lågavlönad'
WHEN salary < 10000
THEN 'Medelavlönad'
ELSE 'Högavlönad'
END
)
FROM employees;
DECODE kan enbart hantera ’=’ så det går inte att lösa det här problemet (på ett enkelt
sätt).
14. Flera tabeller
1 Lista alla anställdas för- och efternamn samt avdelningsnamn
SELECT first_name, last_name, department_name
FROM employees e, departments d
WHERE e.department_id = d.department_id;
2 Som föregående men endast de som har en lön över 10000
SELECT first_name, last_name, department_name, salary
FROM employees e, departments d
WHERE e.department_id = d.department_id AND salary > 10000;
3 Lista alla anställdas för och efternamn, avdelningsnamn men endast de som bor i
Seattle, Toronto eller Oxford.
SELECT first_name, last_name, department_name, city
FROM employees e, departments d, locations l
WHERE e.department_id = d.department_id
AND l.location_id = d.location_id
AND l.city IN ('Seattle', 'Toronto', 'Oxford');
4 Vilken avdelning jobbar Ismael på?
SELECT first_name, last_name, department_name
FROM employees e, departments d
WHERE e.department_id = d.department_id AND first_name = 'Ismael';
5 Visa anställdas namn och avdelningsnamn. Alla avdelningar ska vara med. Även de
som inte har några anställda.
SELECT first_name, last_name, department_name
FROM employees e, departments d
WHERE e.department_id(+) = d.department_id
6 Visa alla anställningsnummer, namn och manager_id i tabellen employees.
SELECT employee_id, first_name, last_name, manager_id
FROM employees;
7 Som föregående men visa även chefens namn.
SELECT e.employee_id, e.first_name, e.last_name, e.manager_id chefid,
(m.first_name || ' ' || m.last_name) AS chef
FROM employees e, employees m
WHERE m.employee_id = e.manager_id;
15. 8 Som föregående men visa även alla som inte har någon chef
SELECT e.employee_id, e.first_name, e.last_name, e.manager_id chefid,
(m.first_name || ' ' || m.last_name) AS chef
FROM employees e, employees m
WHERE m.employee_id(+) = e.manager_id
ORDER BY chef ASC;
Eller enligt ANSI
SELECT e.employee_id, e.first_name, e.last_name, e.manager_id chefid,
(m.first_name || ' ' || m.last_name) AS chef
FROM employees e LEFT OUTER JOIN employees m ON m.employee_id =
e.manager_id
ORDER BY chef ASC;
9 Som föregående men ta även med den anställdes lön och chefens lön. Det är enbart de
personer som har en högre lön än sin chef som ska visas.
SELECT e.employee_id, e.first_name, e.last_name, e.salary,
e.manager_id chefid, (m.first_name || ' ' || m.last_name) AS chef,
m.salary
FROM employees e LEFT OUTER JOIN employees m ON m.employee_id =e.manager_id
WHERE e.salary > m.salary
ORDER BY chef ASC;
10 Hur många anställda finns det på respektive avdelning? Visa avdelningsnamnet och
antalet. Du ska även visa avdelningar som inte har några anställda. I det fallet ska
antalet anställda ska ha värdet 0.
SELECT department_name AS "Avdelning", COUNT (employee_id) AS "Anställda"
FROM employees e, departments d
WHERE e.department_id(+) = d.department_id
GROUP BY department_name
ORDER BY "Anställda" DESC;
11 Visa alla anställdas förnamn, efternamn och land de arbetar i.
SELECT first_name, last_name, country_name
FROM employees e, departments d, locations l, countries c
WHERE d.department_id = e.department_id
AND d.location_id = l.location_id
AND l.country_id = c.country_id;
12 Lista förnamn, efternamn, lön, jobb namn, min lön, max lön för alla jobb som minst
har 4500 i lön. Använd en natural join.
SELECT first_name, last_name, job_title, max_salary, min_salary, salary
FROM employees NATURAL JOIN jobs
WHERE salary >= 4000;
16. 13 Visa department_id för de avdelningar som inte har några anställda. Använd Set
operatorer.
SELECT department_id
FROM departments
MINUS
SELECT department_id
FROM employees;
14 Lista en trädstruktur med förnamn, efternamn, manager_id, job_id samt level. Starta
med personen som har job_id= AD_VP
SELECT employee_id, last_name, first_name, job_id, manager_id, LEVEL
FROM employees
START WITH job_id = 'AD_VP'
CONNECT BY PRIOR employee_id = manager_id;
17. Subfrågor
1 Vilka personer har samma jobb som Bruce Ernst?
SELECT first_name, last_name, job_id
FROM employees
WHERE job_id = (SELECT job_id
FROM employees
WHERE first_name = 'Bruce' AND last_name = 'Ernst');
2 Lista namn och lön på alla personer som har lägre lön än Renske Ladwig. Sortera
fallande efter lön.
SELECT first_name, last_name, salary
FROM employees
WHERE salary < (SELECT salary
FROM employees
WHERE first_name = 'Renske'
AND last_name = 'Ladwig')
ORDER BY salary DESC;
3 Vem eller vilka har den lägsta lönen? Lista förnamn, efternamn och lön.
SELECT first_name, last_name, salary
FROM employees
WHERE salary = (SELECT MIN (salary)
FROM employees);
4 Som ovan men visa även den som har den högsta lönen.
SELECT first_name, last_name, salary
FROM employees
WHERE salary = (SELECT MIN (salary)
FROM employees)
OR salary = (SELECT MAX (salary)
FROM employees)
5 Vem har lägst lön i avdelningen Marketing?
SELECT first_name, last_name, salary
FROM employees
WHERE (salary, department_id) =
(SELECT MIN (salary), e.department_id
FROM employees e, departments d
WHERE d.department_id = e.department_id
AND d.department_name = 'Marketing'
GROUP BY e.department_id);
18. 6 Vilka anställda tjänar mest på respektive avdelning?
SELECT first_name, last_name, salary
FROM employees
WHERE (salary, department_id) IN
(SELECT MAX (salary), e.department_id
FROM employees e, departments d
WHERE d.department_id = e.department_id
GROUP BY e.department_id);
7 Vilken är medellönen för alla som inte är ansvarig för en avdelning?
SELECT AVG (salary)
FROM employees
WHERE (employee_id) NOT IN (SELECT employee_id
FROM employees e, departments d
WHERE d.manager_id = e.employee_id);
8 Vilket jobb (job_id) har den lägsta medellönen.
SELECT job_id, AVG (salary)
FROM employees
GROUP BY job_id
HAVING AVG (salary) IN (SELECT MIN (AVG (salary))
FROM employees e
GROUP BY job_id);
9 Visa alla personer vars lön sämst är 2500 lägre än vad den högst betalda i respektive
avdelning får. Du ska även visa den som har högst betalt.
Detta är en korrelerad subfråga. Observera e.department_id i subfrågan.
SELECT department_id, first_name, last_name, salary
FROM employees e
WHERE salary >= (SELECT MAX (salary) - 2500
FROM employees
WHERE department_id = e.department_id)
ORDER BY department_id, salary DESC;
10 Lista en trädstruktur med förnamn, efternamn, manager_id samt level. Starta med
personen som är chef för IT avdelningen.
SELECT employee_id, last_name, first_name, job_id, manager_id, LEVEL
FROM employees
CONNECT BY PRIOR employee_id = manager_id
START WITH employee_id =
(SELECT employee_id
FROM departments d1, employees e1
WHERE e1.employee_id = d1.manager_id
AND d1.department_name = 'IT')
19. Objekt
DROP TABLE FORETAG CASCADE CONSTRAINTS ;
CREATE TABLE FORETAG (
FORETAGSNR NUMBER (10) NOT NULL,
NAMN VARCHAR2 (50) NOT NULL,
ORGNR VARCHAR2 (30),
POSTADRESS VARCHAR2 (40),
POSTNR VARCHAR2 (20),
ORT VARCHAR2 (30),
LAND VARCHAR2 (40),
TELEFONNUMMER VARCHAR2 (40),
CONSTRAINT FORETAG_PK
PRIMARY KEY ( FORETAGSNR ) ) ;
CREATE INDEX FOR_NAMN_I ON
FORETAG(NAMN)
;
CREATE INDEX FOR_ORGNR_I ON
FORETAG(ORGNR)
;
DROP TABLE UPPDRAG CASCADE CONSTRAINTS ;
CREATE TABLE UPPDRAG (
UPPDRAGSNR NUMBER (10) NOT NULL,
UPPFOLJNNG VARCHAR2 (10),
STATUS VARCHAR2 (10),
STARTDATUM DATE,
SLUTDATUM DATE,
MAXTIMMAR NUMBER (10,2),
FOR_FORETAGSNR NUMBER (10),
CONSTRAINT UPP_UPPDRAGSNR_PK
PRIMARY KEY ( UPPDRAGSNR ) ) ;
DROP TABLE KONSULTER CASCADE CONSTRAINTS ;
CREATE TABLE KONSULTER (
KONSULTNR NUMBER (10) NOT NULL,
PERSONNR VARCHAR2 (10) NOT NULL,
FORNAMN VARCHAR2 (20),
EFTERNAMN VARCHAR2 (40),
KOMPETENSOMRADE VARCHAR2 (20),
SLUTAT DATE,
CONSTRAINT KON_KONSULTNR_PK
PRIMARY KEY ( PERSONNR ) ) ;