Hej Habr!
I mere end 3 år har jeg undervist i SQL i forskellige træningscentre, og en af mine observationer er, at eleverne mestrer og forstår SQL bedre, hvis de får en opgave, og ikke kun taler om mulighederne og det teoretiske grundlag.
I denne artikel vil jeg dele med dig min liste over opgaver, som jeg giver eleverne som hjemmearbejde, og som vi gennemfører forskellige former for brainstorms på, som fører til en dyb og klar forståelse af SQL.
SQL (ˈɛsˈkjuˈɛl; eng. struktureret forespørgselssprog) er et deklarativt programmeringssprog, der bruges til at skabe, ændre og administrere data i en relationsdatabase, der styres af et passende databasestyringssystem.
Du kan læse om SQL fra forskellige
Denne artikel er ikke beregnet til at lære dig SQL fra bunden.
Så lad os gå.
Vi vil bruge det velkendte
Jeg bemærker, at vi kun vil overveje opgaver på SELECT. Der er ingen opgaver på DML og DDL.
opgaver
Begrænsning og sortering af data
Medarbejderbord. Få en liste med oplysninger om alle medarbejdere
beslutning
SELECT * FROM employees
Medarbejderbord. Få en liste over alle medarbejdere ved navn 'David'
beslutning
SELECT *
FROM employees
WHERE first_name = 'David';
Medarbejderbord. Få en liste over alle medarbejdere med job_id svarende til 'IT_PROG'
beslutning
SELECT *
FROM employees
WHERE job_id = 'IT_PROG'
Medarbejderbord. Få en liste over alle medarbejdere fra 50. afdeling (department_id) med en løn (løn) større end 4000
beslutning
SELECT *
FROM employees
WHERE department_id = 50 AND salary > 4000;
Medarbejderbord. Få en liste over alle medarbejdere fra 20. og fra 30. afdeling (afdeling_id)
beslutning
SELECT *
FROM employees
WHERE department_id = 20 OR department_id = 30;
Medarbejderbord. Få en liste over alle medarbejdere, hvis sidste bogstav i deres navn er 'a'
beslutning
SELECT *
FROM employees
WHERE first_name LIKE '%a';
Medarbejderbord. Få en liste over alle medarbejdere fra 50. og fra 80. afdeling (department_id), som har en bonus (værdien i kolonnen commission_pct er ikke tom)
beslutning
SELECT *
FROM employees
WHERE (department_id = 50 OR department_id = 80)
AND commission_pct IS NOT NULL;
Medarbejderbord. Få en liste over alle medarbejdere, hvis navn indeholder mindst 2 bogstaver 'n'
beslutning
SELECT *
FROM employees
WHERE first_name LIKE '%n%n%';
Medarbejderbord. Få en liste over alle medarbejdere, hvis navn er længere end 4 bogstaver
beslutning
SELECT *
FROM employees
WHERE first_name LIKE '%_____%';
Medarbejderbord. Få en liste over alle medarbejdere, hvis løn er mellem 8000 og 9000 (inklusive)
beslutning
SELECT *
FROM employees
WHERE salary BETWEEN 8000 AND 9000;
Medarbejderbord. Få en liste over alle medarbejdere, hvis navn indeholder symbolet '%'
beslutning
SELECT *
FROM employees
WHERE first_name LIKE '%%%' ESCAPE '';
Medarbejderbord. Få en liste over alle manager-id'er
beslutning
SELECT DISTINCT manager_id
FROM employees
WHERE manager_id IS NOT NULL;
Medarbejderbord. Få en liste over medarbejdere med deres stillinger i formatet: Donald(sh_clerk)
beslutning
SELECT first_name || '(' || LOWER (job_id) || ')' employee FROM employees;
Brug af funktioner i en række til at tilpasse output
Medarbejderbord. Få en liste over alle medarbejdere, hvis navn er længere end 10 bogstaver
beslutning
SELECT *
FROM employees
WHERE LENGTH (first_name) > 10;
Medarbejderbord. Få en liste over alle medarbejdere, der har bogstavet 'b' i deres navn (der skelnes mellem store og små bogstaver)
beslutning
SELECT *
FROM employees
WHERE INSTR (LOWER (first_name), 'b') > 0;
Medarbejderbord. Få en liste over alle medarbejdere, hvis navn indeholder mindst 2 bogstaver 'a'
beslutning
SELECT *
FROM employees
WHERE INSTR (LOWER (first_name),'a',1,2) > 0;
Medarbejderbord. Få en liste over alle medarbejdere, hvis løn er et multiplum af 1000
beslutning
SELECT *
FROM employees
WHERE MOD (salary, 1000) = 0;
Medarbejderbord. Få det første 3-cifrede nummer af medarbejderens telefonnummer, hvis hans nummer er i formatet ХХХ.ХХХ.ХХХХ
beslutning
SELECT phone_number, SUBSTR (phone_number, 1, 3) new_phone_number
FROM employees
WHERE phone_number LIKE '___.___.____';
Afdelinger tabel. Få det første ord fra afdelingsnavnet for dem med mere end ét ord i navnet
beslutning
SELECT department_name,
SUBSTR (department_name, 1, INSTR (department_name, ' ')-1)
first_word
FROM departments
WHERE INSTR (department_name, ' ') > 0;
Medarbejderbord. Få medarbejdernavne uden første og sidste bogstav i navnet
beslutning
SELECT first_name, SUBSTR (first_name, 2, LENGTH (first_name) - 2) new_name
FROM employees;
Medarbejderbord. Få en liste over alle medarbejdere, hvis sidste bogstav i navnet er lig med 'm' og længden af navnet er større end 5
beslutning
SELECT *
FROM employees
WHERE SUBSTR (first_name, -1) = 'm' AND LENGTH(first_name)>5;
Dobbelt bord. Få datoen næste fredag
beslutning
SELECT NEXT_DAY (SYSDATE, 'FRIDAY') next_friday FROM DUAL;
Medarbejderbord. Få en liste over alle medarbejdere, der har været i virksomheden i over 17 år
beslutning
SELECT *
FROM employees
WHERE MONTHS_BETWEEN (SYSDATE, hire_date) / 12 > 17;
Medarbejderbord. Få en liste over alle medarbejdere, hvis sidste ciffer i telefonnummeret er ulige og består af 3 tal adskilt af en prik
beslutning
SELECT *
FROM employees
WHERE MOD (SUBSTR (phone_number, -1), 2) != 0
AND INSTR (phone_number,'.',1,3) = 0;
Medarbejderbord. Få en liste over alle medarbejdere, hvis job_id-værdi efter '_'-tegnet har mindst 3 tegn, men denne værdi efter '_' er ikke lig med 'CLERK'
beslutning
SELECT *
FROM employees
WHERE LENGTH (SUBSTR (job_id, INSTR (job_id, '_') + 1)) > 3
AND SUBSTR (job_id, INSTR (job_id, '_') + 1) != 'CLERK';
Medarbejderbord. Få en liste over alle medarbejdere ved at erstatte alle '.' i PHONE_NUMBER-værdien på '-'
beslutning
SELECT phone_number, REPLACE (phone_number, '.', '-') new_phone_number
FROM employees;
Brug af konverteringsfunktioner og betingede udtryk
Medarbejderbord. Få en liste over alle medarbejdere, der kom på arbejde den første dag i måneden (enhver)
beslutning
SELECT *
FROM employees
WHERE TO_CHAR (hire_date, 'DD') = '01';
Medarbejderbord. Få en liste over alle medarbejdere, der kom på arbejde i 2008
beslutning
SELECT *
FROM employees
WHERE TO_CHAR (hire_date, 'YYYY') = '2008';
DOBBELT bord. Vis morgendagens dato i formatet: I morgen er det anden dag i januar
beslutning
SELECT TO_CHAR (SYSDATE, 'fm""Tomorrow is ""Ddspth ""day of"" Month') info
FROM DUAL;
Medarbejderbord. Få en liste over alle medarbejdere og deres startdato i formatet: 21. juni 2007
beslutning
SELECT first_name, TO_CHAR (hire_date, 'fmddth ""of"" Month, YYYY') hire_date
FROM employees;
Medarbejderbord. Få en liste over medarbejdere med øget løn med 20 %. Vis løn med dollartegn
beslutning
SELECT first_name, TO_CHAR (salary + salary * 0.20, 'fm$999,999.00') new_salary
FROM employees;
Medarbejderbord. Få en liste over alle medarbejdere, der kom på arbejde i februar 2007.
beslutning
SELECT *
FROM employees
WHERE hire_date BETWEEN TO_DATE ('01.02.2007', 'DD.MM.YYYY')
AND LAST_DAY (TO_DATE ('01.02.2007', 'DD.MM.YYYY'));
SELECT *
FROM employees
WHERE to_char(hire_date,'MM.YYYY') = '02.2007';
DOBBELT bord. Eksporter aktuel dato, + sekund, + minut, + time, + dag, + måned, + år
beslutning
SELECT SYSDATE now,
SYSDATE + 1 / (24 * 60 * 60) plus_second,
SYSDATE + 1 / (24 * 60) plus_minute,
SYSDATE + 1 / 24 plus_hour,
SYSDATE + 1 plus_day,
ADD_MONTHS (SYSDATE, 1) plus_month,
ADD_MONTHS (SYSDATE, 12) plus_year
FROM DUAL;
Medarbejderbord. Få en liste over alle ansatte med fuld løn (løn + kommission_pct(%)) i formatet: $24,000.00
beslutning
SELECT first_name, salary, TO_CHAR (salary + salary * NVL (commission_pct, 0), 'fm$99,999.00') full_salary
FROM employees;
Medarbejderbord. Få en liste over alle medarbejdere og information om tilgængeligheden af lønbonusser (Ja/Nej)
beslutning
SELECT first_name, commission_pct, NVL2 (commission_pct, 'Yes', 'No') has_bonus
FROM employees;
Medarbejderbord. Få lønniveauet for hver medarbejder: Mindre end 5000 anses for lavt niveau, større end eller lig med 5000 og mindre end 10000 anses for normalt niveau, større end eller lig med 10000 anses for højt niveau
beslutning
SELECT first_name,
salary,
CASE
WHEN salary < 5000 THEN 'Low'
WHEN salary >= 5000 AND salary < 10000 THEN 'Normal'
ELSE 'High'
END salary_level
FROM employees;
Tabel over lande. For hvert land skal du vise den region, hvor det er placeret: 1-Europa, 2-Amerika, 3-Asien, 4-Afrika (uden tilslutning)
beslutning
SELECT country_name country,
DECODE (region_id,
1, 'Europe',
2, 'America',
3, 'Asia',
4, 'Africa',
'Unknown')
region
FROM countries;
SELECT country_name
country,
CASE region_id
WHEN 1 THEN 'Europe'
WHEN 2 THEN 'America'
WHEN 3 THEN 'Asia'
WHEN 4 THEN 'Africa'
ELSE 'Unknown'
END
region
FROM countries;
Rapportering af aggregerede data ved hjælp af gruppefunktionerne
Medarbejderbord. Få en rapport af afdeling_id med minimum og maksimum løn, tidlige og sene ankomst datoer og antal medarbejdere. Sorter efter antal ansatte (desc)
beslutning
SELECT department_id,
MIN (salary) min_salary,
MAX (salary) max_salary,
MIN (hire_date) min_hire_date,
MAX (hire_date) max_hire_Date,
COUNT (*) count
FROM employees
GROUP BY department_id
order by count(*) desc;
Medarbejderbord. Hvor mange medarbejdere, hvis navne starter med det samme bogstav? Sorter efter mængde. Vis kun dem, hvor tallet er større end 1
beslutning
SELECT SUBSTR (first_name, 1, 1) first_char, COUNT (*)
FROM employees
GROUP BY SUBSTR (first_name, 1, 1)
HAVING COUNT (*) > 1
ORDER BY 2 DESC;
Medarbejderbord. Hvor mange medarbejdere arbejder i samme afdeling og får samme løn?
beslutning
SELECT department_id, salary, COUNT (*)
FROM employees
GROUP BY department_id, salary
HAVING COUNT (*) > 1;
Medarbejderbord. Få en rapport over, hvor mange medarbejdere der blev ansat på hver dag i ugen. Sorter efter mængde
beslutning
SELECT TO_CHAR (hire_Date, 'Day') day, COUNT (*)
FROM employees
GROUP BY TO_CHAR (hire_Date, 'Day')
ORDER BY 2 DESC;
Medarbejderbord. Få en rapport om, hvor mange medarbejdere der blev ansat pr. år. Sorter efter mængde
beslutning
SELECT TO_CHAR (hire_date, 'YYYY') year, COUNT (*)
FROM employees
GROUP BY TO_CHAR (hire_date, 'YYYY');
Medarbejderbord. Få antallet af afdelinger, der har ansatte
beslutning
SELECT COUNT (COUNT (*)) department_count
FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id;
Medarbejderbord. Få liste over afdelings-id med mere end 30 ansatte
beslutning
SELECT department_id
FROM employees
GROUP BY department_id
HAVING COUNT (*) > 30;
Medarbejderbord. Få en liste over afdelings-id'er og den afrundede gennemsnitlige løn for medarbejdere i hver afdeling.
beslutning
SELECT department_id, ROUND (AVG (salary)) avg_salary
FROM employees
GROUP BY department_id;
Tabel over lande. Få en liste over region_id summen af alle bogstaver i alle lande_navne, hvor mere end 60
beslutning
SELECT region_id
FROM countries
GROUP BY region_id
HAVING SUM (LENGTH (country_name)) > 60;
Medarbejderbord. Få en liste over afdelings-id, hvor ansatte i flere (>1) job-id arbejder
beslutning
SELECT department_id
FROM employees
GROUP BY department_id
HAVING COUNT (DISTINCT job_id) > 1;
Medarbejderbord. Få en liste over manager_id, hvis antal underordnede er større end 5 og summen af alle lønninger for hans underordnede er større end 50000
beslutning
SELECT manager_id
FROM employees
GROUP BY manager_id
HAVING COUNT (*) > 5 AND SUM (salary) > 50000;
Medarbejderbord. Få en liste over manager_id, hvis gennemsnitlige løn for alle hans underordnede er mellem 6000 og 9000, som ikke modtager bonusser (commission_pct er tom)
beslutning
SELECT manager_id, AVG (salary) avg_salary
FROM employees
WHERE commission_pct IS NULL
GROUP BY manager_id
HAVING AVG (salary) BETWEEN 6000 AND 9000;
Medarbejderbord. Få den maksimale løn fra alle ansatte job_id, der slutter med ordet 'CLERK'
beslutning
SELECT MAX (salary) max_salary
FROM employees
WHERE job_id LIKE '%CLERK';
SELECT MAX (salary) max_salary
FROM employees
WHERE SUBSTR (job_id, -5) = 'CLERK';
Medarbejderbord. Få den maksimale løn blandt alle gennemsnitslønningerne for afdelingen
beslutning
SELECT MAX (AVG (salary))
FROM employees
GROUP BY department_id;
Medarbejderbord. Få antallet af medarbejdere med det samme antal bogstaver i deres navn. Vis samtidig kun dem, hvis navn er længere end 5, og antallet af medarbejdere med samme navn er mere end 20. Sorter efter navnelængde
beslutning
SELECT LENGTH (first_name), COUNT (*)
FROM employees
GROUP BY LENGTH (first_name)
HAVING LENGTH (first_name) > 5 AND COUNT (*) > 20
ORDER BY LENGTH (first_name);
SELECT LENGTH (first_name), COUNT (*)
FROM employees
WHERE LENGTH (first_name) > 5
GROUP BY LENGTH (first_name)
HAVING COUNT (*) > 20
ORDER BY LENGTH (first_name);
Visning af data fra flere tabeller ved hjælp af joins
Tabelmedarbejdere, afdelinger, lokationer, lande, regioner. Få en liste over regioner og antallet af ansatte i hver region
beslutning
SELECT region_name, COUNT (*)
FROM employees e
JOIN departments d ON (e.department_id = d.department_id)
JOIN locations l ON (d.location_id = l.location_id)
JOIN countries c ON (l.country_id = c.country_id)
JOIN regions r ON (c.region_id = r.region_id)
GROUP BY region_name;
Tabelmedarbejdere, afdelinger, lokationer, lande, regioner. Få detaljerede oplysninger om hver enkelt medarbejder:
Fornavn, Efternavn, Afdeling, Job, Gade, Land, Region
beslutning
SELECT First_name,
Last_name,
Department_name,
Job_id,
street_address,
Country_name,
Region_name
FROM employees e
JOIN departments d ON (e.department_id = d.department_id)
JOIN locations l ON (d.location_id = l.location_id)
JOIN countries c ON (l.country_id = c.country_id)
JOIN regions r ON (c.region_id = r.region_id);
Medarbejderbord. Vis alle ledere, der har mere end 6 ansatte
beslutning
SELECT man.first_name, COUNT (*)
FROM employees emp JOIN employees man ON (emp.manager_id = man.employee_id)
GROUP BY man.first_name
HAVING COUNT (*) > 6;
Medarbejderbord. Vis alle medarbejdere, der ikke rapporterer til nogen
beslutning
SELECT emp.first_name
FROM employees emp
LEFT JOIN employees man ON (emp.manager_id = man.employee_id)
WHERE man.FIRST_NAME IS NULL;
SELECT first_name
FROM employees
WHERE manager_id IS NULL;
Medarbejdertabel, Jobhistorie. Medarbejderbordet gemmer alle medarbejdere. Tabellen Jobhistorie gemmer medarbejdere, der forlod virksomheden. Få en rapport om alle medarbejdere og deres status i virksomheden (Ansat eller forladt virksomheden med afrejsedato)
Eksempel:
fornavn | status
jennifer | Forlod virksomheden den 31. december 2006
Clara | Arbejder i øjeblikket
beslutning
SELECT first_name,
NVL2 (
end_date,
TO_CHAR (end_date, 'fm""Left the company at"" DD ""of"" Month, YYYY'),
'Currently Working')
status
FROM employees e LEFT JOIN job_history j ON (e.employee_id = j.employee_id);
Tabelmedarbejdere, afdelinger, lokationer, lande, regioner. Få en liste over medarbejdere, der bor i Europa (region_name)
beslutning
SELECT first_name
FROM employees
JOIN departments USING (department_id)
JOIN locations USING (location_id)
JOIN countries USING (country_id)
JOIN regions USING (region_id)
WHERE region_name = 'Europe';
SELECT first_name
FROM employees e
JOIN departments d ON (e.department_id = d.department_id)
JOIN locations l ON (d.location_id = l.location_id)
JOIN countries c ON (l.country_id = c.country_id)
JOIN regions r ON (c.region_id = r.region_id)
WHERE region_name = 'Europe';
Bordmedarbejdere, afdelinger. Vis alle afdelinger med mere end 30 ansatte
beslutning
SELECT department_name, COUNT (*)
FROM employees e JOIN departments d ON (e.department_id = d.department_id)
GROUP BY department_name
HAVING COUNT (*) > 30;
Bordmedarbejdere, afdelinger. Vis alle medarbejdere, der ikke er i nogen afdeling
beslutning
SELECT first_name
FROM employees e
LEFT JOIN departments d ON (e.department_id = d.department_id)
WHERE d.department_name IS NULL;
SELECT first_name
FROM employees
WHERE department_id IS NULL;
Bordmedarbejdere, afdelinger. Vis alle afdelinger uden ansatte
beslutning
SELECT department_name
FROM employees e
RIGHT JOIN departments d ON (e.department_id = d.department_id)
WHERE first_name IS NULL;
Medarbejderbord. Vis alle medarbejdere, der ikke har nogen underordnede
beslutning
SELECT man.first_name
FROM employees emp
RIGHT JOIN employees man ON (emp.manager_id = man.employee_id)
WHERE emp.FIRST_NAME IS NULL;
Bordmedarbejdere, job, afdelinger. Vis medarbejdere i formatet: Fornavn, Jobtitel, Afdelingsnavn.
Eksempel:
fornavn | stillingsbetegnelse | Afdelingsnavn
Anders | forsendelse | Ekspedient Forsendelse
beslutning
SELECT first_name, job_title, department_name
FROM employees e
JOIN jobs j ON (e.job_id = j.job_id)
JOIN departments d ON (d.department_id = e.department_id);
Medarbejderbord. Få en liste over medarbejdere, hvis ledere fik et job i 2005, men samtidig fik disse arbejdere selv et job før 2005
beslutning
SELECT emp.*
FROM employees emp JOIN employees man ON (emp.manager_id = man.employee_id)
WHERE TO_CHAR (man.hire_date, 'YYYY') = '2005'
AND emp.hire_date < TO_DATE ('01012005', 'DDMMYYYY');
Medarbejderbord. Få en liste over medarbejdere, hvis ledere fik et job i januar måned ethvert år, og længden af jobtitlen for disse medarbejdere er mere end 15 tegn
beslutning
SELECT emp.*
FROM employees emp
JOIN employees man ON (emp.manager_id = man.employee_id)
JOIN jobs j ON (emp.job_id = j.job_id)
WHERE TO_CHAR (man.hire_date, 'MM') = '01' AND LENGTH (j.job_title) > 15;
Brug af underforespørgsler til at løse forespørgsler
Medarbejderbord. Få en liste over medarbejdere med det længste navn.
beslutning
SELECT *
FROM employees
WHERE LENGTH (first_name) =
(SELECT MAX (LENGTH (first_name)) FROM employees);
Medarbejderbord. Få en liste over medarbejdere med en løn, der er større end gennemsnitslønnen for alle ansatte.
beslutning
SELECT *
FROM employees
WHERE salary > (SELECT AVG (salary) FROM employees);
Bordmedarbejdere, afdelinger, lokationer. Få den by, hvor medarbejderne tjener mindst i alt.
beslutning
SELECT city
FROM employees e
JOIN departments d ON (e.department_id = d.department_id)
JOIN locations l ON (d.location_id = l.location_id)
GROUP BY city
HAVING SUM (salary) =
( SELECT MIN (SUM (salary))
FROM employees e
JOIN departments d ON (e.department_id = d.department_id)
JOIN locations l ON (d.location_id = l.location_id)
GROUP BY city);
Medarbejderbord. Få en liste over medarbejdere, hvis leder modtager en løn på mere end 15000.
beslutning
SELECT *
FROM employees
WHERE manager_id IN (SELECT employee_id
FROM employees
WHERE salary > 15000)
Bordmedarbejdere, afdelinger. Vis alle afdelinger uden ansatte
beslutning
SELECT *
FROM departments
WHERE department_id NOT IN (SELECT department_id
FROM employees
WHERE department_id IS NOT NULL);
Medarbejderbord. Vis alle medarbejdere, der ikke er ledere
beslutning
SELECT *
FROM employees
WHERE employee_id NOT IN (SELECT manager_id
FROM employees
WHERE manager_id IS NOT NULL)
Medarbejderbord. Vis alle ledere, der har mere end 6 ansatte
beslutning
SELECT *
FROM employees e
WHERE (SELECT COUNT (*)
FROM employees
WHERE manager_id = e.employee_id) > 6;
Bordmedarbejdere, afdelinger. Vis medarbejdere, der arbejder i IT-afdelingen
beslutning
SELECT *
FROM employees
WHERE department_id = (SELECT department_id
FROM departments
WHERE department_name = 'IT');
Bordmedarbejdere, job, afdelinger. Vis medarbejdere i formatet: Fornavn, Jobtitel, Afdelingsnavn.
Eksempel:
fornavn | stillingsbetegnelse | Afdelingsnavn
Anders | forsendelse | Ekspedient Forsendelse
beslutning
SELECT first_name,
(SELECT job_title
FROM jobs
WHERE job_id = e.job_id)
job_title,
(SELECT department_name
FROM departments
WHERE department_id = e.department_id)
department_name
FROM employees e;
Medarbejderbord. Få en liste over medarbejdere, hvis ledere fik et job i 2005, men samtidig fik disse arbejdere selv et job før 2005
beslutning
SELECT *
FROM employees
WHERE manager_id IN (SELECT employee_id
FROM employees
WHERE TO_CHAR (hire_date, 'YYYY') = '2005')
AND hire_date < TO_DATE ('01012005', 'DDMMYYYY');
Medarbejderbord. Få en liste over medarbejdere, hvis ledere fik et job i januar måned ethvert år, og længden af jobtitlen for disse medarbejdere er mere end 15 tegn
beslutning
SELECT *
FROM employees e
WHERE manager_id IN (SELECT employee_id
FROM employees
WHERE TO_CHAR (hire_date, 'MM') = '01')
AND (SELECT LENGTH (job_title)
FROM jobs
WHERE job_id = e.job_id) > 15;
Det er alt for nu.
Jeg håber, at opgaverne var interessante og spændende.
Jeg vil tilføje til denne liste så meget som muligt.
Jeg vil også være glad for eventuelle kommentarer og forslag.
PS: Hvis nogen kommer med en interessant opgave på SELECT, så skriv i kommentarerne, jeg tilføjer den til listen.
Tak.
Kilde: www.habr.com