Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Допы 2012.docx
Скачиваний:
11
Добавлен:
24.09.2019
Размер:
125.27 Кб
Скачать
  1. Дана символьная строка, в которой отдельные слова разделены любым количеством пробелов.

Написать запрос, который выводит строку с 1 пробелом между словами, убирая лидирующие и концевые пробелы.

SELECT REPLACE(REPLACE(REPLACE(TRIM( ' ' FROM '&test_name'), ' ', ' *'), '* ', ''), '*', '') AS "Our string"

FROM DUAL;

  1. //Условие задачи:

//В таблицу записана информация об удачных и неудачных попытках подключения к базе данных (пользователь, время, удачно/неудачно).

//Требуется получить список пользователей, которые совершили подряд три неудачные попытки подключения.

//1 Создаем таблицу

// USERNAME - имя пользователя

// LOGIN_DATE - число, дата, когда пользователь пытался зайти в систему

// LOGIN_RESULT - флаг успешности попытки подключения.

// Если в этом столбце у пользователя стоит 1, значит, попытка подключения была успешной,

// если же 0 - то попытка неуспешна.

//

CREATE TABLE users

(

USERNAME VARCHAR2(25),

LOGIN_DATE DATE,

LOGIN_RESULT NUMBER(9,2)

);

//2 Проверим, все ли так, как нам хотелось.

//

Describe users;

//3 Вставляем данные. Три пользователя Pearson, Chalke и Hendricks 14 раз попытались подключиться к базе данных.

// В ответе должны содержаться пользователи Pearson и Hendricks.

//

INSERT INTO users

VALUES ('Pearson', '01.04.12', 1);

INSERT INTO users

VALUES ('Chalke', '03.04.12', 0);

INSERT INTO users

VALUES ('Chalke', '04.04.12', 1);

INSERT INTO users

VALUES ('Hendricks', '03.04.12', 0);

INSERT INTO users

VALUES ('Hendricks', '03.04.12', 1);

INSERT INTO users

VALUES ('Chalke', '07.04.12', 1);

INSERT INTO users

VALUES ('Hendricks', '06.04.12', 0);

INSERT INTO users

VALUES ('Chalke', '08.04.12', 1);

INSERT INTO users

VALUES ('Pearson', '10.04.12', 0);

INSERT INTO users

VALUES ('Pearson', '10.04.12', 0);

INSERT INTO users

VALUES ('Hendricks', '11.04.12', 0);

INSERT INTO users

VALUES ('Chalke', '14.04.12', 1);

INSERT INTO users

VALUES ('Pearson', '10.04.12', 0);

INSERT INTO users

VALUES ('Hendricks', '12.04.12', 0);

//4 Проверяем содержимое таблицы users

//

SELECT *

FROM users;

//5 Идея осталась ровно такой же, только поместил все в один большой запрос.

// С помощью подзапросов последовательно сортирую исходную таблицу и добавляю к ней столбец num.

SELECT t1.username

FROM (SELECT ROWNUM num, t.*

FROM (SELECT *

FROM users

ORDER BY username, login_date) t) t1

JOIN (SELECT ROWNUM num, t.*

FROM (SELECT *

FROM users

ORDER BY username, login_date) t) t2

ON t1.username=t2.username

JOIN (SELECT ROWNUM num, t.*

FROM (SELECT *

FROM users

ORDER BY username, login_date) t) t0

ON t2.username=t0.username

WHERE t2.num-1=t1.num

AND t2.login_result = t1.login_result

AND t1.login_result = 0

AND t0.num-1=t2.num

AND t0.login_result = t2.login_result

AND t2.login_result = 0

GROUP BY t1.username;

  1. Для каждой таблицы вывести имя таблицы, текст первого ограничения Check, количество столбцов в первом ограничении Check, текст второго ограничения Check, количество столбцов во втором ограничении Check, общее число ограничений Check.

WITH

tab_data AS (SELECT ROWNUM R_NUM, c_name, t_name, s_con

FROM (SELECT constraint_name AS "C_NAME", table_name AS "T_NAME", search_condition AS "S_CON"

FROM user_constraints

WHERE constraint_type = 'C'

ORDER BY t_name, c_name )),

counts AS (SELECT t_name, MIN(R_NUM) AS "MIN_R_NUM", MAX(R_NUM) AS "MAX_R_NUM"

FROM tab_data

GROUP BY t_name),

res_tab AS (SELECT tab_data.t_name AS "T_NAME", tab_data.c_name, tab_data.s_con, R_NUM - MIN_R_NUM +1 AS "C_POS", MAX_R_NUM - MIN_R_NUM +1 AS "COUNTS"

FROM tab_data INNER JOIN counts

ON tab_data.t_name = counts.t_name),

col_count AS (SELECT constraint_name AS "C_NAME", col_count

FROM user_constraints

NATURAL JOIN (SELECT constraint_name, COUNT(column_name) AS "COL_COUNT"

FROM user_cons_columns

GROUP BY constraint_name)

WHERE constraint_type ='C')

SELECT tab1.t_name AS "TABLE_NAME", tab1.s_con AS "FISRT_CONSTRAINT", tab1.col_count AS "C1_COLUMN_COUNT",

tab2.s_con AS "SECOND_CONSTRAINT", tab2.col_count AS "C2_COLUMN_COUNT", tab1.counts AS "CONSTRAINT_NUM"

FROM (SELECT *

FROM res_tab NATURAL JOIN col_count ) tab1

LEFT JOIN (SELECT *

FROM res_tab NATURAL JOIN col_count

WHERE c_pos = '2') tab2

ON tab1.t_name = tab2.t_name

WHERE tab1.c_pos = '1';

//---------------------------------------------------------------------------------------

//tab_data

SELECT ROWNUM R_NUM, c_name, t_name, s_con

FROM (SELECT constraint_name AS "C_NAME", table_name AS "T_NAME", search_condition AS "S_CON"

FROM user_constraints

WHERE constraint_type = 'C'

ORDER BY t_name );

//counts

SELECT table_name, MIN(R_NUM) AS "MIN_R_NUM", MAX(R_NUM) AS "MAX_R_NUM"

FROM (SELECT ROWNUM R_NUM, constraint_name, table_name, search_condition

FROM (SELECT constraint_name, table_name, search_condition

FROM user_constraints

WHERE constraint_type = 'C'

ORDER BY table_name ))

GROUP BY table_name

ORDER BY table_name;

//res_tab

SELECT tab_data.t_name AS "T_NAME", tab_data.c_name, tab_data.s_con, R_NUM - MIN_R_NUM +1 AS "C_POS", MAX_R_NUM - MIN_R_NUM +1 AS "COUNTS"

FROM (SELECT ROWNUM R_NUM, c_name, t_name, s_con

FROM (SELECT constraint_name AS "C_NAME", table_name AS "T_NAME", search_condition AS "S_CON"

FROM user_constraints

WHERE constraint_type = 'C'

ORDER BY t_name, c_name )) tab_data

INNER JOIN (SELECT t_name, MIN(R_NUM) AS "MIN_R_NUM", MAX(R_NUM) AS "MAX_R_NUM"

FROM (SELECT ROWNUM R_NUM, c_name, t_name, s_con

FROM (SELECT constraint_name AS "C_NAME", table_name AS "T_NAME", search_condition AS "S_CON"

FROM user_constraints

WHERE constraint_type = 'C'

ORDER BY t_name ))

GROUP BY t_name) counts

ON tab_data.t_name = counts.t_name;

//col_count

SELECT constraint_name AS "C_NAME", col_count

FROM user_constraints

NATURAL JOIN (SELECT constraint_name, COUNT(column_name) AS "COL_COUNT"

FROM user_cons_columns

GROUP BY constraint_name)

WHERE constraint_type ='C';

WITH

tab_data AS (SELECT ROWNUM R_NUM, c_name, t_name, s_con

FROM (SELECT constraint_name AS "C_NAME", table_name AS "T_NAME", search_condition AS "S_CON"

FROM user_constraints

WHERE constraint_type = 'C'

ORDER BY t_name, c_name )),

counts AS (SELECT t_name, MIN(R_NUM) AS "MIN_R_NUM", MAX(R_NUM) AS "MAX_R_NUM"

FROM tab_data

GROUP BY t_name),

res_tab AS (SELECT tab_data.t_name AS "T_NAME", tab_data.c_name, tab_data.s_con, R_NUM - MIN_R_NUM +1 AS "C_POS", MAX_R_NUM - MIN_R_NUM +1 AS "COUNTS"

FROM tab_data INNER JOIN counts

ON tab_data.t_name = counts.t_name),

col_count AS (SELECT constraint_name AS "C_NAME", col_count

FROM user_constraints

NATURAL JOIN (SELECT constraint_name, COUNT(column_name) AS "COL_COUNT"

FROM user_cons_columns

GROUP BY constraint_name)

WHERE constraint_type ='C')

SELECT *

FROM (SELECT *

FROM res_tab NATURAL JOIN col_count ) tab1

LEFT JOIN (SELECT *

FROM res_tab NATURAL JOIN col_count

WHERE c_pos = '2') tab2

ON tab1.t_name = tab2.t_name ;

  1. Показать в одном отчете для каждого отдела: его номер, наименование, количество работающих сотрудников, средний оклад вместе со следующими данными по каждому сотруднику – фамилия, оклад и должность.

--Вариант с аналитическими функциями

SELECT CASE WHEN d_id IS NULL THEN ' ' ELSE TO_CHAR(d_id) END "Номер отдела",

CASE WHEN department_name IS NULL THEN ' ' ELSE department_name END "Название отдела",

CASE WHEN num IS NULL THEN ' ' ELSE TO_CHAR(num) END "Количество сотрудников",

CASE WHEN avg IS NULL THEN ' ' ELSE TO_CHAR(avg) END "Средняя зарплата",

CASE WHEN last_name IS NULL THEN ' ' ELSE last_name END "Фамилия сотрудника",

CASE WHEN salary IS NULL THEN ' ' ELSE TO_CHAR(salary) END "Оклад",

CASE WHEN job_title IS NULL THEN ' ' ELSE job_title END "Должность"

FROM (SELECT e.department_id d_id, d.department_name,

COUNT(*) OVER (PARTITION BY e.department_id) num,

ROUND(AVG(salary) OVER (PARTITION BY e.department_id), 0) avg,

last_name, salary, job_title,

d.department_id dep_id

FROM employees e LEFT JOIN departments d ON e.department_id=d.department_id JOIN jobs USING (job_id))

GROUP BY GROUPING SETS((d_id, department_name, num, avg),(last_name,dep_id,salary,job_title))

ORDER BY (CASE WHEN d_id IS NULL THEN dep_id ELSE d_id END), d_id, salary DESC nulls FIRST;

--Вариант без аналитических фукций, основной вариант

SELECT CASE WHEN d_id IS NULL THEN ' ' ELSE TO_CHAR(d_id) END "Номер отдела",

CASE WHEN department_name IS NULL THEN ' ' ELSE department_name END "Название отдела",

CASE WHEN num IS NULL THEN ' ' ELSE TO_CHAR(num) END "Количество сотрудников",

CASE WHEN avg IS NULL THEN ' ' ELSE TO_CHAR(avg) END "Средняя зарплата",

CASE WHEN last_name IS NULL THEN ' ' ELSE last_name END "Фамилия сотрудника",

CASE WHEN salary IS NULL THEN ' ' ELSE TO_CHAR(salary) END "Оклад",

CASE WHEN job_title IS NULL THEN ' ' ELSE job_title END "Должность"

FROM (

SELECT d_id, d.department_name department_name, num, avg, e.last_name last_name, d.department_id dep_id, e.salary salary, job_title

FROM

(SELECT department_id d_id,

COUNT(*) num,

ROUND(AVG(salary), 0) avg

FROM employees

GROUP BY department_id) JOIN departments d ON d_id = d.department_id

RIGHT JOIN employees e ON e.department_id = d.department_id JOIN jobs USING (job_id)

)

GROUP BY GROUPING SETS((d_id, department_name, num, avg),(last_name,dep_id,salary,job_title))

ORDER BY (CASE WHEN d_id IS NULL THEN dep_id ELSE d_id END), d_id, salary DESC nulls FIRST;