Pull to refresh

Comments 63

Таблица Employees. Получить список всех сотрудников у которых длинна имени больше 4 букв
Решение
SELECT *
FROM employees
WHERE first_name LIKE '%____%';


Интересное решение.
Обычно использую прямо в лоб LENGTH(first_name) > 4 (как в другом примере здесь видел)
Какие есть преимущества у такого способа по сравнению с length?

И спасибо за задачки — очень интересно.
Конечно же тут лучше использовать функцию length.
Данное решение здесь указано так потому что задача находится в теме «Restricting and Sorting Data», а предпологается что на этом этапе (это начало SQL) студент еще не знает о существовании функции length.
Разумеется, функцию LENGTH использовать нельзя, т.к. это обойдется нам в index scan, как минимум.

DedZamkad
SELECT *
FROM employees
WHERE first_name LIKE '%____%';

И так тоже не хорошо, т.к. из %% тоже получим сканирование индекса.
Вот так, при некотором везении, получим seek:
WHERE first_name LIKE '[А-Я][-''. А-Я][-''. А-Я][-''. А-Я]%'
Ну, конечно, тут придется еще дополнительно учесть регистр, если коллейшн регистрозависимый, и особенности хранения данных.
Например — грязь в виде лидирующих пробелов (чего быть не должно), пробелов, тире, точек, апострофов внутри составного имени ([-''. А-Я] — как раз учитывает это).
Впрочем, это всё для MSSQLSERVER, а в ставке Гитлера — все малохольные а у Оракула — всё иначе.
:-)
О. Хорошая штука.
В MSSQLSERVER — так нельзя. Придется явно создать в таблице вычисляемое поле, и проиндексировать его. Тогда оно будет подхватываться функцией во Where, если выражение будет тем же самым.
Может, я что-то не понимаю, но чтобы выполнялось условие «длина>4» не должно ли здесь быть 5 символов подчеркивания вместо 4?
Верно подмечено) Спасибо, исправил
Кстати, явное преимущество у length в читаемости запроса.
Но даже если использовать LIKE — один из знаков процента (причём любой) явно избыточен.

Более того достаточно условия first_name LIKE '____%'

UFO just landed and posted this here
Принципиальной разницы нет. Оба варианта верны и имеют место быть
UFO just landed and posted this here
--почему не YEAR(DATE) а какой то ужас с текстом?
В Оракле для работы с датой используется функция TO_DATE. YEAR(DATE) — в оракле такого на сколько я знаю нет.

Схему базы можно взять тут
UFO just landed and posted this here
SELECT EXTRACT (MONTH FROM SYSDATE) FROM DUAL

но все равно TO_DATE, TO_CHAR очень удобные и функциональные. С EXTRACT активно не имел дело
DataGrip кстати предлагает такую траснформацию в коде :)image
UFO just landed and posted this here
Последнее верно :)
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
Самое интересное — это при помощи селект выбор графа.
пусть будет таблица ID родитель, остальные колонки — дети.
у детей могут быть дети в этой или другой таблице, и т.п.
выбрать всех детей родителя, так называемый субсет.

Интересно как сама БД реагирует на селект. Наивное решение было бы просмотреть все строки и выбрать нужные, но подозреваю там оптимизации в виде неких хешей вроде
значение поля -> все строки где это значение.
Проведите свое собственное расследование и напишите статью на хабре об этом и поделитесь тут ) я с удовольствием почитаю
Таблица Employees. Получить список сотрудников менеджеры которых устроились на работу в январе месяце любого года и длинна job_title этих сотрудников больше 15ти символов

Не лучше ли требовать со студентов решение с JOIN-ами вместо подзапросов, приучать к хорошему стилю?
Эта задача есть как и в теме Join так и в теме Subqueries. Correlated subsquery можно заменить joinами и наобарот. Я всетаки предпочитаю чтобы студенты знали это.

В идеале, студенты должны уметь преобразовывать запросы из одной формы в другую и обратно.
Работать ведь со всяким придется. Если научить только хорошему стилю, то при чтения запросов в плохом стиле, будут проблемы.

Такие задачки очень удобно решать в каком-нибудь конструкторе запросов, в MS Access, например. :)

ещё прикольная у меня идейка сделать интерпретатор естественного языка вроде предложение на обычнося языке -> запрос

На мой взгляд, тренироваться писать SQL запросы в конструкторе — зло. Это может быть и удобно чтобы порешать задачки, но на практическое применение переносится крайне плохо. Где будет ваш конструктор, когда вам нужно будет забрать данные по jdbc/odbc?

писать SQL запросы в конструкторе — зло

Так и запишем, Microsoft делает злые вещи.


тренироваться писать SQL запросы в конструкторе — зло

Наоборот, очень помогло по-быстрому освоить SQL.


Это может быть и удобно чтобы порешать задачки, но на практическое применение переносится крайне плохо.

В 90-x очень плотно работал с базами данными. Очень сильно помогало по-быстрому строить запросы и отчеты. Конструкторы запросов — это про быструю разработку.


Где будет ваш конструктор, когда вам нужно будет забрать данные по jdbc/odbc?

Рядом будет. В результатах работы конструктора мы имеет также и сам SQL запрос.

Конструкторы запросов — это про быструю разработку.

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


Рядом будет. В результатах работы конструктора мы имеет также и сам SQL запрос.

Я правильно понимаю, что вы сразу используете тот запрос, который вам сгенерировал конструктор, и никак его не допиливаете?
Какой был самый сложный запрос, который вы писали?

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

Какие-то простые запросы может и да. Несколько более сложные запросы проще накидать в конструкторе.


Я правильно понимаю, что вы сразу используете тот запрос, который вам сгенерировал конструктор, и никак его не допиливаете?

Нет, конечно-же, случай бывает разный. Иногда приходится экспериментировать.


Какой был самый сложный запрос, который вы писали?

Большой-большой секрет маленькой компании.


В начале освоения SQL конструктор очень хорошо помогал. Сейчас, кончено, и без конструктора могу. Конструктор еще помогал найти решения, о которых я бы даже и не подозревал зная только стандарт SQL. Что помогало строить запросы одной строчкой, без необходимости писать дополнительный код и выполнять несколько запросов, создавая лишнюю работу и лишний трафик между клиентом и сервером БД.

сразу написать запрос получится быстрее, чем накликивать его мышкой в конструкторе.
не всегда :). Порой, всё же, быстрее накликать 15 таблиц, чтобы через внешние ключи из 3-х таблиц выбрать несколько столбцов, да ещё и с парой фильтров по связующим таблицам. Но, надо помнить, что конструктор придуман не для разработчиков. И запросы там могут быть не оптимальны.

Спасибо за статью.
Расскажите, вы намеренно собрали запросы с группировкой и с having в один раздел?
Как студенты справлялись с появлением сразу двух новых концепций?


Можете добавить, на каких примерах вы объясняли каждую из тем?

--Расскажите, вы намеренно собрали запросы с группировкой и с having в один раздел?
Я преподаю по официальной книге по подготовке к сертификации. И в ней having и group by в одной и теме. Они связаны, их лучше проходить вместе.

--Можете добавить, на каких примерах вы объясняли каждую из тем?
Так вот целью данной статьи и было показать какие задачи мы решаем со студентами по темам. Я разделил задачи по темам.
целью данной статьи и было показать какие задачи мы решаем со студентами по темам.

Это понятно. Но вы ведь перед началом решения даёте какую то теорию? Какой пример вы разбираете в каждой из тем?

У меня есть ppt презентации от Oracle для преподователей. По ним и провожу уроки

Ещё интересно, как проверяете решения?
Глазами смотрите в запрос или как-то более надёжно?
Что делаете, если у студента оригинальное решение?
Что если данных много и глазами проверить трудно?

Хороший вопрос. В основном проверяю на глаз потому что сразу вижу что не так и правильно ли составлен SQL. Если что то сложное и оригинальное решение проверяю в первую очередь верен ли результат выполнения, во вторую — саму реализацию. Стараюсь придерживатся принципа KISS

Посмотрите как на sql-ex.ru проверка делается (где-то там рассказывались детали).

И все статистические оконные функции, и outer/cross apply, да даже банального exists нет (а в главе Using Subqueries to Solve Queries точно есть задачи, которые удобнее и понятнее решать exists). Не увидел union/except/intersect.
Есть запросы, где разный регистр ключевых слов ("Reporting Aggregated Data Using the Group Functions" — первая задача)
В некоторых запросах учит откровенно плохому (мне глаз резануло WHERE TO_CHAR (hire_date, 'YYYY') = '2008')
Дальше просто лень перечислять.


Итого — так себе списочек.

Спасибо за отзыв ) Буду рад вашим подробным замечаниям… напишите пожалуйста что бы вы исправили.

EXISTS — задач нет, но добавлю в список.
union/except/intersect — это тема также идет после subqueries. Ее тоже добавлю.

Конечно задачи для новичков и тех кто учится SQL. Для человека опытного задачи могут показаться не интересными и не нужными. Предложите свой список. Было бы интересно глянуть
Так проблема не в списочке задач а в списочке решений :)
Ну так напишите ваши решения ) В чем проблема? поделитесь знаниями)
Это был не комент к посту, а комент к коменту
Тут половина задач тривиальны, есть куча кривоватых решений…
Совсем не понятно, почему это названо занимательными задачами.
Предложите пожалуйста ваши решения там где считаете что решение кривое. Будет полезно как и мне так и всем читателям. Спасибо
На кривоватость вам уже указали. Скажите лучше, с какой стороны эти задачки занимательны?
так вы таки скажите как выбрать с помощью select граф или ещё называется субсет?

Получается, что ваши студенты смогут найти решение любой из ваших задач в интернете просто загуглив условие?
Я попробовал на "Таблица Employees. Получить список сотрудников с самым длинным именем." и первая ссылка в выдаче — на эту статью.

Решение задачи «Таблица Employees. Получить список всех сотрудников у которых последня цифра телефонного номера нечетная и состоит из 3ех чисел разделенных точкой» — неверное. Запрос вернёт любые значения, где последний символ — чётная цифра, а количество точек не превышает 2. Одна точка, нет точек, куча букв — неважно. Ибо схема на поле PHONE_NUMBER вообще никаких ограничений не накладывает, кроме указания типа, и туда можно писать что угодно — хоть кличку любимого попугая.
Решение задачи «Таблица Employees. Получить список всех сотрудников у которых в значении job_id после знака '_' как минимум 3 символа но при этом это значение после '_' не равно 'CLERK'» также неверно. Запись со значением JOB_ID = 'IS_A_CLERK' будет выведена… и со значением 'AA_BB_CC'… Знак подчёркивания следует искать от конца (третий параметр функции INSTR равен -1).
Решение задачи «Таблица Employees. Получить уровень зарплаты каждого сотрудника: Меньше 5000 считается Low level, Больше или равно 5000 и меньше 10000 считается Normal level, Больше иои равно 10000 считается High level» неверное. Если salary не указано (в поле NULL — на поле нет ограничения NOT NULL) — для такой записи будет выведено 'High', что вряд ли можно считать корректным…
да, учитывая возможность там NULL значений запрос можно переписать в виде
SELECT first_name,
       salary,
       CASE
           WHEN salary < 5000 THEN 'Low'
           WHEN salary >= 5000 AND salary < 10000 THEN 'Normal'
           WHEN salary >= 10000 THEN 'High'
           ELSE 'Unknown'
       END
           salary_level
  FROM employees;
Мы предпологаем что в job_id всего один символ "_" и поэтому ищем первое его вхождение.

--Запись со значением JOB_ID = 'IS_A_CLERK' будет выведена
не будет, так как не удовлетворяет условию
LENGTH (SUBSTR (job_id, INSTR (job_id, '_') + 1)) > 3


--и со значением 'AA_BB_CC'
не будет выведена, так как не удовлетворяет обоим условиям
По мнению livesql.oracle.com значения
SELECT LENGTH (SUBSTR ('IS_A_CLERK', INSTR ('IS_A_CLERK', '_') + 1)) FROM DUAL;
SELECT LENGTH (SUBSTR ('AA_BB_CC', INSTR ('AA_BB_CC', '_') + 1)) FROM DUAL;
равны 7 и 5 соответственно. Оба больше 3. Так что первое условие удовлетворяется для обоих значений.

По его же мнению значения
SELECT SUBSTR ('IS_A_CLERK', INSTR ('IS_A_CLERK', '_') + 1) FROM DUAL;
SELECT SUBSTR ('AA_BB_CC', INSTR ('AA_BB_CC', '_') + 1) FROM DUAL;
равны 'A_CLERK' и 'BB_CC', оба не равны 'CLERK', так что и второе условие удовлетворяется для обоих значений.

Итого — оба значения будут выведены.

Мы предпологаем что в job_id всего один символ "_"
Вот только Вы как-то забыли явно указать этот, несомненно важный, момент. А структурой данных, на которую Вы ссылаетесь, подобные ограничения не устанавливаются.
Добавил условие на проверку наличия второй точки.
SELECT *
  FROM employees
 WHERE     MOD (SUBSTR (phone_number, -1), 2) != 0
       AND INSTR (phone_number,'.',1,3) = 0
       AND INSTR (phone_number,'.',1,2) > 0;
А как насчёт проверки, что
состоит из 3ех чисел разделенных точкой

А то, знаете ли, какое-нибудь 'AAA.BBB.CCC4' выведется, хотя и не соответствует предъявленным требованиям. И никаких ограничений в структуре, запрещающих указанное значение, опять-таки нет.
Sign up to leave a comment.

Articles