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 landed and left these words here
Принципиальной разницы нет. Оба варианта верны и имеют место быть
UFO landed and left these words here
--почему не YEAR(DATE) а какой то ужас с текстом?
В Оракле для работы с датой используется функция TO_DATE. YEAR(DATE) — в оракле такого на сколько я знаю нет.

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

но все равно TO_DATE, TO_CHAR очень удобные и функциональные. С EXTRACT активно не имел дело
DataGrip кстати предлагает такую траснформацию в коде :)image
UFO landed and left these words here
UFO landed and left these words here
UFO landed and left these words here
UFO landed and left these words 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