Sqlглава 6 о других предложениях и конструкциях sql


Содержание

Подзапросы SQL

Что такое подзапрос в SQL?

  • SQL подзапрос — это запрос, вложенный в другой запрос;
  • Подзапрос может использоваться:

o В инструкции SELECT ;
o В инструкции FROM ;
o В условии WHERE .

  • Подзапрос может быть вложен в инструкции SELECT , INSERT , UPDATE или DELETE , а также в другой подзапрос;
  • Подзапрос обычно добавляется в условие WHERE оператора SQL SELECT ;
  • Можно использовать операторы сравнения, такие как >, ANY или ALL ;
  • Подзапрос также называется внутренним запросом. Оператор, содержащий подзапрос, также называется внешним;
  • Внутренний запрос выполняется перед родительским запросом, чтобы результаты его работы могли быть переданы внешнему.

Подзапрос можно использовать в инструкциях SELECT , INSERT , DELETE или UPDATE для выполнения следующих задач:

  • Сравнения выражения с результатом запроса;
  • Определения того, включено ли выражение в результаты запроса;
  • Проверки того, выбирает ли запрос любые строки.
  • Подзапрос SQL ( внутренний запрос ) выполняется перед выполнением основного запроса ( внешнего запроса );
  • Основной запрос использует результат выполнения подзапроса.

Примеры подзапросов SQL

В этом разделе мы рассмотрим, как использовать подзапросы. У нас есть следующие две таблицы: ‘ student ‘ и ‘ marks ‘ с общим полем ‘ StudentID ‘:

Теперь нужно составить запрос, определяющий всех студентов, которые получают лучшие отметки, чем студент со StudentID — « V002 ». Но мы не знаем отметок студента « V002 ».

Поэтому нужно составить два SQL подзапроса в Select . Один запрос возвращает отметки ( хранятся в поле « Total_marks » ) для « V002 », а второй запрос выбирает учеников, которые получают лучшие оценки, чем результат первого запроса.

Результатом запроса будет 80 .

Используя результат этого запроса, мы написали еще один запрос, чтобы определить учеников, которые получают оценки лучше, чем 80 .

Два приведенных запроса определяют студентов, которые получают лучше оценки, чем студент StudentID « V002 » ( Abhay ).

Можно объединить эти два запроса, вложив один запрос в другой. Подзапрос — это запрос внутри круглых скобок. Рассмотрим подзапроса в SQL пример :

Графическое представление подзапроса SQL :

Подзапросы: общие правила

Ниже приведен синтаксис подзапроса :

Подзапросы: рекомендации по использованию

Ниже приведен ряд рекомендаций, которым нужно следовать при использовании SQL подзапросов:

  • Подзапрос должен быть заключен в круглые скобки;
  • Подзапрос должен указываться в правой части оператора сравнения;
  • Подзапросы не могут обрабатывать свои результаты, поэтому в подзапрос не может быть добавлено условие ORDER BY ;
  • Используйте однострочные операторы с однострочными подзапросами;
  • Если подзапрос возвращает во внешний запрос значение null , внешний запрос не будет возвращать никакие строки при использовании операторов сравнения в условии WHERE .

Типы подзапросов

  • Однострочный подзапрос : возвращает ноль или одну строку;
  • Многострочный подзапрос : возвращает одну или несколько строк;
  • Многостолбцовый подзапрос : возвращает один или несколько столбцов;
  • Коррелированные подзапросы : указывают один или несколько столбцов во внешней инструкции SQL . Такой подзапрос называется коррелированным, поскольку он связан с внешней инструкцией SQL ;
  • Вложенные подзапросы : подзапросы помещенные в другой подзапрос.

Также можно использовать подзапрос внутри инструкций INSERT , UPDATE и DELETE .

Подзапросы с инструкцией INSERT

Инструкция INSERT может использоваться с подзапросами SQL .

Если мы хотим вставить заказы из таблицы ‘ orders ‘, для которых в таблице « neworder » значение advance_amount составляет 2000 или 5000 , можно использовать следующий код SQL :

Пример таблицы: orders

ORD_NUM ORD_AMOUNT ADVANCE_AMOUNT ORD_DATE CUST_CODE AGENT_CODE ORD_DESCRIPTION
———- ———- ————— ——— ————— ————— ——————
200114 3500 2000 15-AUG-08 C00002 A008
200122 2500 400 16-SEP-08 C00003 A004
200118 500 100 20-JUL-08 C00023 A006
200119 4000 700 16-SEP-08 C00007 A010
200121 1500 600 23-SEP-08 C00008 A004
200130 2500 400 30-JUL-08 C00025 A011
200134 4200 1800 25-SEP-08 C00004 A005
200108 4000 600 15-FEB-08 C00008 A004
200103 1500 700 15-MAY-08 C00021 A005
200105 2500 500 18-JUL-08 C00025 A011
200109 3500 800 30-JUL-08 C00011 A010
200101 3000 1000 15-JUL-08 C00001 A008
200111 1000 300 10-JUL-08 C00020 A008
200104 1500 500 13-MAR-08 C00006 A004
200106 2500 700 20-APR-08 C00005 A002
200125 2000 600 10-OCT-08 C00018 A005
200117 800 200 20-OCT-08 C00014 A001
200123 500 100 16-SEP-08 C00022 A002
200120 500 100 20-JUL-08 C00009 A002
200116 500 100 13-JUL-08 C00010 A009
200124 500 100 20-JUN-08 C00017 A007
200126 500 100 24-JUN-08 C00022 A002
200129 2500 500 20-JUL-08 C00024 A006
200127 2500 400 20-JUL-08 C00015 A003
200128 3500 1500 20-JUL-08 C00009 A002
200135 2000 800 16-SEP-08 C00007 A010
200131 900 150 26-AUG-08 C00012 A012
200133 1200 400 29-JUN-08 C00009 A002
200100 1000 600 08-JAN-08 C00015 A003
200110 3000 500 15-APR-08 C00019 A010
200107 4500 900 30-AUG-08 C00007 A010
200112 2000 400 30-MAY-08 C00016 A007
200113 4000 600 10-JUN-08 C00022 A002
200102 2000 300 25-MAY-08 C00012 A012

Подзапросы с инструкцией UPDATE

В инструкции UPDATE можно установить новое значение столбца, равное результату, возвращаемому однострочным подзапросом. Ниже приводится синтаксис и пример UPDATE с подзапросом SQL .

Если мы хотим изменить параметры ord_date в таблице ‘ neworder ‘ с ‘ 15 -JAN-10 ‘, для которых разница между ord_amount и advance_amount меньше минимальной ord_amount в таблице ‘ orders ‘,то можно использовать следующий код SQL :

Пример таблицы: neworder

ORD_NUM ORD_AMOUNT ADVANCE_AMOUNT ORD_DATE CUST_CODE AGENT_CODE ORD_DESCRIPTION
———- ———- ————— ——— ————— ————— ——————
200114 3500 2000 15-AUG-08 C00002 A008
200122 2500 400 16-SEP-08 C00003 A004
200118 500 100 20-JUL-08 C00023 A006
200119 4000 700 16-SEP-08 C00007 A010
200121 1500 600 23-SEP-08 C00008 A004
200130 2500 400 30-JUL-08 C00025 A011
200134 4200 1800 25-SEP-08 C00004 A005
200108 4000 600 15-FEB-08 C00008 A004
200103 1500 700 15-MAY-08 C00021 A005
200105 2500 500 18-JUL-08 C00025 A011
200109 3500 800 30-JUL-08 C00011 A010
200101 3000 1000 15-JUL-08 C00001 A008
200111 1000 300 10-JUL-08 C00020 A008
200104 1500 500 13-MAR-08 C00006 A004
200106 2500 700 20-APR-08 C00005 A002
200125 2000 600 10-OCT-08 C00018 A005
200117 800 200 20-OCT-08 C00014 A001
200123 500 100 16-SEP-08 C00022 A002
200120 500 100 20-JUL-08 C00009 A002
200116 500 100 13-JUL-08 C00010 A009
200124 500 100 20-JUN-08 C00017 A007
200126 500 100 24-JUN-08 C00022 A002
200129 2500 500 20-JUL-08 C00024 A006
200127 2500 400 20-JUL-08 C00015 A003
200128 3500 1500 20-JUL-08 C00009 A002
200135 2000 800 16-SEP-08 C00007 A010
200131 900 150 26-AUG-08 C00012 A012
200133 1200 400 29-JUN-08 C00009 A002
200100 1000 600 08-JAN-08 C00015 A003
200110 3000 500 15-APR-08 C00019 A010
200107 4500 900 30-AUG-08 C00007 A010
200112 2000 400 30-MAY-08 C00016 A007
200113 4000 600 10-JUN-08 C00022 A002
200102 2000 300 25-MAY-08 C00012 A012

Подзапросы с инструкцией DELETE

Ниже приводится синтаксис и пример использования SQL подзапросов с инструкцией DELETE .

Если нужно удалить заказы из таблицы « neworder », для которых advance_amount меньше максимального значения advance_amount из таблицы « orders », можно использовать следующий код SQL :

Пример таблицы: neworder

ORD_NUM ORD_AMOUNT ADVANCE_AMOUNT ORD_DATE CUST_CODE AGENT_CODE ORD_DESCRIPTION
———- ———- ————— ——— ————— ————— ——————
200114 3500 2000 15-AUG-08 C00002 A008
200122 2500 400 16-SEP-08 C00003 A004
200118 500 100 20-JUL-08 C00023 A006
200119 4000 700 16-SEP-08 C00007 A010
200121 1500 600 23-SEP-08 C00008 A004
200130 2500 400 30-JUL-08 C00025 A011
200134 4200 1800 25-SEP-08 C00004 A005
200108 4000 600 15-FEB-08 C00008 A004
200103 1500 700 15-MAY-08 C00021 A005
200105 2500 500 18-JUL-08 C00025 A011
200109 3500 800 30-JUL-08 C00011 A010
200101 3000 1000 15-JUL-08 C00001 A008
200111 1000 300 10-JUL-08 C00020 A008
200104 1500 500 13-MAR-08 C00006 A004
200106 2500 700 20-APR-08 C00005 A002
200125 2000 600 10-OCT-08 C00018 A005
200117 800 200 20-OCT-08 C00014 A001
200123 500 100 16-SEP-08 C00022 A002
200120 500 100 20-JUL-08 C00009 A002
200116 500 100 13-JUL-08 C00010 A009
200124 500 100 20-JUN-08 C00017 A007
200126 500 100 24-JUN-08 C00022 A002
200129 2500 500 20-JUL-08 C00024 A006
200127 2500 400 20-JUL-08 C00015 A003
200128 3500 1500 20-JUL-08 C00009 A002
200135 2000 800 16-SEP-08 C00007 A010
200131 900 150 26-AUG-08 C00012 A012
200133 1200 400 29-JUN-08 C00009 A002
200100 1000 600 08-JAN-08 C00015 A003
200110 3000 500 15-APR-08 C00019 A010
200107 4500 900 30-AUG-08 C00007 A010
200112 2000 400 30-MAY-08 C00016 A007
200113 4000 600 10-JUN-08 C00022 A002
200102 2000 300 25-MAY-08 C00012 A012

Данная публикация представляет собой перевод статьи « SQL Subqueries » , подготовленной дружной командой проекта Интернет-технологии.ру

14 наиболее часто используемых запросов SQL на собеседовании (вопрос/ответ)

Главное меню » Базы данных » Учебное пособие по SQL » 14 наиболее часто используемых запросов SQL на собеседовании (вопрос/ответ)

Эти запросы проверят ваши SQL навыки на работу, как внутреннее и внешнее соединение, фильтрация записей с помощью условий WHERE и HAVING, группировка записей с помощью предложения GROUP BY, вычисление суммы, среднего и подсчета записей с помощью совокупной функции как AVG(), SUM () и COUNT (), поиск записей с помощью символов подстановки в операторе LIKE, поиска записей в связанном с использованием BETWEEN и IN, запросы DATE и TIME и т.д. Если вы столкнулись с каким – либо интересным запросом в SQL или у вас есть какие – либо проблемы и поиск решения, вы можете разместить его здесь на благо каждого.

SQL Query. Вопросы и ответы

Вопрос 1: SQL-запрос, чтобы найти вторую самую высокую зарплату работника

Ответ: Есть много способов найти вторую самую высокую зарплату работника в SQL, вы можете использовать либо в SQL объединение или подзапрос, чтобы решить эту проблему. Вот SQL-запрос с использованием подзапроса:

См как найти вторую самую высокую зарплату в SQL с большим количеством способов решения этой проблемы.


Вопрос 2: SQL-запрос, чтобы найти максимальную зарплату от каждого отдела.

Ответ: Вы можете найти максимальную зарплату для каждого отдела, группируя все записи по DeptId, а затем с помощью функции MAX(), чтобы вычислить максимальную зарплату в каждой группе или каждого отдела.

Эти вопросы становятся более интересными, если Интервьюер попросит вас напечатать название отдела вместо отдела ID, в этом случае, вам нужно соединить таблицу Employee с Department с использованием внешнего ключа DeptID, убедитесь, что вы используете LEFT or RIGHT OUTER JOIN включая отделов без каких – либо сотрудников. Вот запрос

В этом запросе мы использовали RIGHT OUTER JOIN, потому что нам нужно название отдела из таблицы Department, который находится на правой стороне JOIN, даже если нет никакого упоминания о dept_id в таблице сотрудников.

Вопрос 3: Написать SQL – запрос для отображения текущей даты.

Ответ: SQL имеет встроенную функцию под названием GetDate(), которая возвращает текущую временную метку. Это будет работать в Microsoft SQL Server, другие производители, такие как Oracle и MySQL также имеет эквивалентные функции.


Вопрос 4: Напишите SQL запрос, чтобы проверить дату в передаваемом запросе, является ли дата данного формата или нет .

Ответ: SQL имеет функцию IsDate(), которая используется для проверки переданное значение, является дата или не указанного формата, он возвращает 1 (истина) или 0 (ложь), соответственно. Помните IsDate() является функцией MSSQL и он может не работать на Oracle, MySQL или любой другой базе данных, но не было бы что – то подобное.

Она возвращает 0, потому что прошло дата не в правильном формате.


Вопрос 5: Напишите SQL запрос, чтобы напечатать имя отдельного работника у которого поле DOB составляет от 01/02/1965 до 31/11/1970.

Ответ: Этот SQL-запрос является сложным, но вы можете использовать BETWEEN, чтобы получить все записи, у которых дата выпадает между двумя датами.

Вопрос 6: написать SQL запрос, где найти количество сотрудников в зависимости от пола , чье поле DOB между 01/02/1965 до 31/11/1970.

Вопрос 7: Напишите SQL запрос, чтобы найти сотрудника, чья зарплата равна или превышает 20000.

Вопрос 8: Напишите SQL запрос, чтобы найти имя сотрудника, чье имя начинается с ‘M’

Вопрос 9: Найти все записи о сотрудниках, содержащие слово “Роман”, независимо от того, был ли он, как РОМАН, Роман, или роман.

Вопрос 10: Напишите SQL запрос, чтобы найти год от даты.

Ответ: Вот как вы можете найти год от даты в SQL Server 2008

Вопрос 11: Написать SQL – запрос для поиска дубликатов строк в базе данных? а затем написать SQL запрос, чтобы удалить их?
Ответ: Вы можете использовать следующий запрос для выбора различных записей:

Вопрос 12: Существует таблица, которая содержит два столбца Student и Marks, вам нужно найти всех студентов, чьи оценки являются больше, чем средние оценки, т.е. список студентов выше среднего.

Ответ: Этот запрос можно записать с помощью подзапросов, как показано ниже:


Вопрос 13: Как вы находите всех сотрудников, которые являются также менеджерами?
Вы дали стандартную таблицу сотрудников с дополнительной колонкой mgr_id , которая содержит идентификатор сотрудника менеджера.

Ответ: Вы должны знать о автообъединение, чтобы решить эту проблему. В автообъединение, вы можете присоединить два экземпляра одной и той же таблицы, чтобы выяснить дополнительные подробности, как показано ниже

Запрос покажет имя сотрудника и имя менеджера в два столбца, например

Один из последующих изменит этот запрос, чтобы включать в себя сотрудников, которые не имеют статус менеджера. Для того, чтобы решить, что, вместо этого использовать inner join, просто используйте left outer join, он также будет включать сотрудников без менеджеров.

Вопрос 14: У вас есть композитный индекс из трех колонок, как вы обеспечиваете значение двух столбцов в WHERE на выборку? Будет ли индекс использоваться для этой операции?

Например, если индекс находится на EmpId, EmpFirstName и EmpSecondName и вы пишете запрос типа

Если данные в две колонки являются вторичными индексами столбца, то индекс не будет ссылаться, но если данные 2 колонок содержат первичный индекс (первый столбец при создании индекса), то индекс будет ссылаться. В этом случае индекс будет использоваться, поскольку EmpId и EmpFirstName являются первичные столбцы.

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

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Обзор основных SQL запросов

Каждый сайт в Интернете, любой проект, обрабатывающий значительный объем информации, вынужден хранить эту информацию в тех или иных базах данных (БД). Подавляющее большинство проектов информацию сохраняют в БД реляционного типа, делая записи в различных подобиях таблиц. Как внесение новых записей, так и обращение к имеющимся, осуществляется с благодаря использованию запросов, составляемых конструкциями SQL (structured query language) – непроцедурного декларативного языка структурированных запросов. В нашем случае это подразумевает, что, используя конструкции SQL, мы будем обращаться к БД, сообщая что нужно сделать с данными, но не указывая способ, как именно это нужно сделать.


Фактически, SQL является набором стандартов, для написания запросов к БД. Последняя действующая редакция стандартов языка SQL — ISO/IEC 9075:2020.

Основываясь на указанных стандартах языка SQL, ряд организаций выпустили свои, расширенные версии стандартов указанного языка. Подобные версии иногда называют диалектами SQL.

Варианты спецификаций SQL разрабатываются компаниями и сообществами и служат, соответственно, для работы с разными СУБД (Системами Управления Базами Данных) – системами программ, заточенных под работу с продуктами из своей инфраструктуры.

Наиболее применяемые на сегодня СУБД, использующие свои стандарты (расширения) SQL:

MySQL – СУБД, принадлежащая компании Oracle.

PostgreSQL – свободная СУБД, поддерживаемая и развиваемая сообществом.

Microsoft SQL Server – СУБД, принадлежащая компании Microsoft. Применяет диалект Transact-SQL (T-SQL).

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

Общими чертами диалектов являются основные конструкции, применимые практически без отличий во многих реляционных БД. Основные отличия диалектов состоят в различиях использованных типов данных, количеством, реализацией и детальными возможностями команд. Разные диалекты применяют как разные наборы зарезервированных слов, так и разные наборы команд.

Здесь мы будем рассматривать запросы, применяя конструкции из спецификаций диалекта T-SQL.

Коснемся классификации SQL запросов.

Выделяют такие виды SQL запросов:

DDL (Data Definition Language) язык определения данных. Задачей DDL запросов является создание БД и описание ее структуры. Запросами такого вида устанавливаются правила того, в каком виде различные данные будут размещаться в БД.

DML (Data Manipulation Language) — язык манипулирования данными. В число запросов этого типа входят различные команды, используя которые непосредственно производятся некоторые манипуляции с данными. DML-запросы нужны для добавления изменений в уже внесенные данные, для получения данных из БД, для их сохранения, для обновления различных записей и для их удаления из БД. В число элементов DML-обращений входит основная часть SQL операторов.

DCL (Data Control Language) — язык управления данными. Включает в себя запросы и команды, касающиеся разрешений, прав и других настроек СУБД.

TCL (Transaction Control Language) — язык управления транзакциями. Конструкции такого типа применяют чтобы управлять изменениями, которые производятся с использованием DML запросов. Конструкции TCL позволяют нам производить объединение DML запросов в наборы транзакций.

Основные типы SQL запросов по их видам:

Ниже мы рассмотрим практические примеры применения SQL запросов для взаимодействия с БД используя запросы двух категорий – DDL и DML.

Создание и настройка базы данных

Нам нужна будет для примеров БД MS SQL Server 2020 и MS SQL Server Management Studio 2020.

Рассмотрим последовательность действий того, как создать SQL запрос. Воспользовавшись Management Studio, для начала создадим новый редактор скриптов. Чтобы это сделать, на стандартной панели инструментов выберем «Создать запрос». Или воспользуемся клавиатурной комбинацией Ctrl+N.

Нажимая кнопку «Создать запрос» в Management Studio, мы открываем тестовый редактор, используя который можно производить написание SQL запросов, сохранять их и запускать.

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

Создадим новую БД с именем «b_library» для библиотеки книг. Чтобы это делать наберем в редакторе такой SQL запрос:

Далее выделим введенный текст и нажмем F5 или кнопку «Выполнить». У нас создастся БД «b_library».

Все дальнейшие манипуляции мы можем провести с этой созданной нами БД. Для этого сначала подключимся к этой базе:

В БД «b_library» создадим таблицу авторов «tAuthors» с такими столбцами: AuthorId, AuthorFirstName, AuthorLastName, AuthorAge:

Заполним нашу таблицу таким авторами: Александр Пушкин, Сергей Есенин, Джек Лондон, Шота Руставели и Рабиндранат Тагор. Для этого используем такой SQL запрос:

Мы можем посмотреть в «tAuthors» записи, путем отправления в СУБД простого SQL запроса:

В нашей БД «b_library» мы создали первую таблицу «tAuthors», заполнили «tAuthors» авторами книг и теперь можем рассмотреть различные примеры SQL запросов, которыми мы сможем взаимодействовать с БД.

Примеры простых запросов SQL к базам данных.

Рассмотрим основные запросы SQL.

SELECT

1) Выведем все имеющиеся у нас БД:

2) Выведем все таблицы в созданной нами ранее БД «b_library»:

3) Выводим еще раз имеющиеся у нас записи по авторам книг из созданной выше «tAuthors»:

4) Выведем информацию о том, сколько у нас имеется записей строк в «tAuthors»:

5) Выведем из «tAuthors» две записи, начиная с четвертой. Используя ключевое слово OFFSET, пропустим первые три записи, а благодаря использованию ключевого слова FETCH – обозначим выборку только следующих 2 строк (ONLY):

6) Выведем из «tAuthors» все записи с сортировкой в алфавитном порядке по первой букве имени автора:

7) Выведем из «tAuthors» данные, предварительно по AuthorId отсортировав их по убыванию:

8) Выберем записи из «tAuthors», значение AuthorFirstName у которых соответствует имени «Александр»:

9) Выберем из «tAuthors» записи, где имя автора AuthorFirstName начинается с «се»:

10) Выберем из «tAuthors» записи, в которых имя автора (AuthorFirstName) заканчивается на «ат»:

11) Сделаем выборку всех строк из «tAuthors», значение AuthorId в которых равняется 2 или 4:

12) Выберем в «tAuthors» такую запись AuthorAge, значение которой — наибольшее:

13) Проведем выборку из «tAuthors» по столбцам AuthorFirstName и AuthorLastName:

14) Получим из «tAuthors» все строки, у которых AuthorId не равняется трем:

INSERT

INSERT – это вид запроса SQL, при применении которого СУБД выполняет добавление новых записей в БД.

Добавим в «tAuthors» нового автора – Уильяма Шекспира, 51 год. Соответственно в поле AuthorFirstName добавится Уильям, в AuthorLastName добавится Шекспир, в AuthorAge – 51. В AuthorId, в нашем случае, автоматически добавится значение, инкрементированное от предыдущего на 1.

UPDATE

UPDATE – SQL запрос, позволяющий внести изменения или дописывать новую информацию в те записи, которые уже существуют.

Внесем корректировки в шестую запись (Author >

Затем, обратимся к БД, чтобы вывести все имеющиеся записи:

Мы видим изменения информации в записи автора под номером 6.

DELETE

DELETE – SQL запрос, выполняя который в СУБД производится операция удаления определенной строки из таблицы в БД.

Обратимся к «tAuthors» с командой на удаление строки, где Author >

Чтобы увидеть изменения, снова обратимся к базе для вывода всех записей:

Мы видим, что запись автора под номером 5 теперь отсутствует в «tAuthors» и, соответственно, не выводится с другими записями.

DROP

DROP – ключевое слово в SQL, применяемое для удаления данных с помощью запроса. К примеру удаление некоторой таблицы из БД.

После рассмотрения ряда простых запросов к БД мы можем полностью удалить нашу таблицу «tAuthors» целиком, выполнив простой SQL запрос:

Далее рассмотрим сложные запросы SQL.

Примеры сложных запросов к базе данных MS SQL

Сложные запросы SQL представляют из себя комбинации простых запросов. Выполняясь, простые запросы возвращают сгруппированные в промежуточные таблицы наборы данных. А сложный запрос уже манипулирует данными, полученными благодаря простым «подзапросам».

Сложные запросы получаются следующими способами:

  1. Помещением одного запроса в другой. В этом случае внешнее выражение будет называться основным запросом, а вложенное выражение — подзапросом.
  2. Применение с SQL запросами различных операторов объединения результатов выполнения подзапросов. Такие операторы называют реляционными.

Рассмотрим в SQL примеры сложных запросов.

Воспользуемся нашей предыдущей таблицей «tAuthors» и создадим дополнительно еще одну таблицу с книгами этих авторов – «tBooks». В качестве идентификатора авторов книг используем значение AuthorId из «tAuthors», а название книги — BookTitle.

Заполним «tBooks» такими книгами:

1) Сделаем выборку из БД всех книг, у которых имя автора — «Александр»:

2) Сделаем выборку данных из «tBooks» всех книг, авторами которых являются люди, с именами «Александр» или «Сергей»:

3) Сделаем выборку по книгам из таблицы «tBooks», у которых именами авторов являются НЕ «Сергей» и НЕ «Александр»:

4) Возьмем таблицу «tBooks» и сделаем из нее выборку всех книг с указанием как имен, так и фамилий авторов этих книг из «tAuthors»:

Выводы

Мы с вами рассмотрели несколько вариантов простых и сложных SQL запросов. Конечно эту статью не стоит рассматривать ни как учебное пособие, ни как исчерпывающий перечень возможностей запросов в T-SQL, и других диалектах. Скорее ее можно считать примером SQL запросов для начинающих. Однако она может послужить для Вас отправной точкой.

SELECT — предложение OVER (Transact-SQL) SELECT — OVER Clause (Transact-SQL)

ОБЛАСТЬ ПРИМЕНЕНИЯ: SQL Server База данных SQL Azure Azure Synapse Analytics (хранилище данных SQL) Parallel Data Warehouse APPLIES TO: SQL Server Azure SQL Database Azure Synapse Analytics (SQL DW) Parallel Data Warehouse

Определяет секционирование и упорядочение набора строк до применения соответствующей оконной функции. Determines the partitioning and ordering of a rowset before the associated window function is applied. То есть предложение OVER определяет окно или определяемый пользователем набор строк внутри результирующего набора запроса. That is, the OVER clause defines a window or user-specified set of rows within a query result set. Затем оконная функция вычисляет значение для каждой строки в окне. A window function then computes a value for each row in the window. Вы можете использовать предложение OVER вместе с функциями для вычисления статистических значений, например для вычисления скользящих средних, суммарных статистических выражений, промежуточных итогов или первых N результатов в группе. You can use the OVER clause with functions to compute aggregated values such as moving averages, cumulative aggregates, running totals, or a top N per group results.

Синтаксис Syntax

Аргументы Arguments

PARTITION BY PARTITION BY
Разделяет результирующий набор запроса на секции. Divides the query result set into partitions. Оконная функция применяется к каждой секции отдельно, и вычисление начинается заново для каждой секции. The window function is applied to each partition separately and computation restarts for each partition.

value_expression value_expression
Определяет столбец, по которому секционируется набор строк. Specifies the column by which the rowset is partitioned. Аргумент value_expression может ссылаться только на столбцы, сделанные доступными с помощью предложения FROM. value_expression can only refer to columns made available by the FROM clause. Аргумент value_expression не может ссылаться на выражения или псевдонимы в списке выбора. value_expression cannot refer to expressions or aliases in the select list. Выражение value_expression может быть выражением столбца, скалярным вложенным запросом, скалярной функцией или пользовательской переменной. value_expression can be a column expression, scalar subquery, scalar function, or user-defined variable.

Определяет логический порядок строк в каждой секции результирующего набора. Defines the logical order of the rows within each partition of the result set. То есть он указывает логический порядок, в котором выполняется вычисление оконной функции. That is, it specifies the logical order in which the window functioncalculation is performed.

order_by_expression order_by_expression
Указывает столбец или выражение, по которому производится сортировка. Specifies a column or expression on which to sort. Аргумент order_by_expression может ссылаться только на столбцы, сделанные доступными с помощью предложения FROM. order_by_expression can only refer to columns made available by the FROM clause. Нельзя указывать целое число для обозначения имени или псевдонима столбца. An integer cannot be specified to represent a column name or alias.

COLLATE collation_name COLLATE collation_name
Указывает, что операция ORDER BY должна выполняться в соответствии с параметрами сортировки, указанными в аргументе collation_name. Specifies that the ORDER BY operation should be performed according to the collation specified in collation_name. Аргументом collation_name может быть либо имя параметров сортировки Windows, либо имя параметров сортировки SQL. collation_name can be either a Windows collation name or a SQL collation name. Дополнительные сведения см. в статье Collation and Unicode Support. For more information, see Collation and Unicode Support. Аргумент COLLATE применяется только к столбцам типа char, varchar, nchar и nvarchar. COLLATE is applicable only for columns of type char, varchar, nchar, and nvarchar.

ASC | DESC ASC | DESC
Указывает порядок сортировки значений в указанном столбце — по возрастанию или по убыванию. Specifies that the values in the specified column should be sorted in ascending or descending order. Порядок сортировки по умолчанию — ASC. ASC is the default sort order. Значения NULL рассматриваются как минимально возможные значения. Null values are treated as the lowest possible values.

ROWS | RANGE ROWS | RANGE
Применимо к: с SQL Server 2012 (11.x) SQL Server 2012 (11.x) до SQL Server 2020 SQL Server 2020 . Applies to: SQL Server 2012 (11.x) SQL Server 2012 (11.x) through SQL Server 2020 SQL Server 2020 .

Еще больше ограничивает строки в пределах секции, указывая начальную и конечную точки. Further limits the rows within the partition by specifying start and end points within the partition. Это достигается путем указания диапазона строк в отношении текущей строки с помощью логических или физических взаимосвязей. This is done by specifying a range of rows with respect to the current row either by logical association or physical association. Физическая взаимосвязь достигается с помощью предложения ROWS. Physical association is achieved by using the ROWS clause.

Илон Маск рекомендует:  Uue кодирование


Предложение ROWS ограничивает строки внутри секции путем указания фиксированного числа строк, предшествующих или следующих после текущей строки. The ROWS clause limits the rows within a partition by specifying a fixed number of rows preceding or following the current row. В качестве альтернативы предложение RANGE логически ограничивает строки внутри секции путем указания диапазона значений в отношении к значению текущей строки. Alternatively, the RANGE clause logically limits the rows within a partition by specifying a range of values with respect to the value in the current row. Предшествующие и последующие строки определяются на основании порядка, заданного в предложении ORDER BY. Preceding and following rows are defined based on the ordering in the ORDER BY clause. Рамка окна «RANGE … CURRENT ROW . » содержит все строки, которые имеют те же значения в выражении ORDER BY, что и в текущей строке. The window frame «RANGE . CURRENT ROW . » includes all rows that have the same values in the ORDER BY expression as the current row. Например, ROWS BETWEEN 2 PRECEDING AND CURRENT ROW означает, что окно строк, с которым работает функция, содержит всего три строки, при этом текущей строке предшествуют 2 строки (включая текущую). For example, ROWS BETWEEN 2 PRECEDING AND CURRENT ROW means that the window of rows that the function operates on is three rows in size, starting with 2 rows preceding until and including the current row.

Предложения ROWS и RANGE требуют, чтобы было указано предложение ORDER BY. ROWS or RANGE requires that the ORDER BY clause be specified. Если предложение ORDER BY содержит несколько выражений порядка, то CURRENT ROW FOR RANGE при определении текущей строки учитывает все столбцы в списке ORDER BY. If ORDER BY contains multiple order expressions, CURRENT ROW FOR RANGE considers all columns in the ORDER BY list when determining the current row.

UNBOUNDED PRECEDING UNBOUNDED PRECEDING
Применимо к: с SQL Server 2012 (11.x) SQL Server 2012 (11.x) до SQL Server 2020 SQL Server 2020 . Applies to: SQL Server 2012 (11.x) SQL Server 2012 (11.x) through SQL Server 2020 SQL Server 2020 .

Указывает, что окно начинается с первой строки секции. Specifies that the window starts at the first row of the partition. UNBOUNDED PRECEDING может быть указано только как начальная точка окна. UNBOUNDED PRECEDING can only be specified as window starting point.

PRECEDING PRECEDING
Указывается со для обозначения числа строк или значений перед текущей строкой. Specified with to indicate the number of rows or values to precede the current row. Эта спецификация не допускается в предложении RANGE. This specification is not allowed for RANGE.

CURRENT ROW CURRENT ROW
Применимо к: с SQL Server 2012 (11.x) SQL Server 2012 (11.x) до SQL Server 2020 SQL Server 2020 . Applies to: SQL Server 2012 (11.x) SQL Server 2012 (11.x) through SQL Server 2020 SQL Server 2020 .

Указывает, что окно начинается или заканчивается на текущей строке при использовании совместно с предложением ROWS или что окно заканчивается на текущем значении при использовании с предложением RANGE. Specifies that the window starts or ends at the current row when used with ROWS or the current value when used with RANGE. CURRENT ROW может быть задана и как начальная, и как конечная точка. CURRENT ROW can be specified as both a starting and ending point.

BETWEEN AND BETWEEN AND
Применимо к: с SQL Server 2012 (11.x) SQL Server 2012 (11.x) до SQL Server 2020 SQL Server 2020 . Applies to: SQL Server 2012 (11.x) SQL Server 2012 (11.x) through SQL Server 2020 SQL Server 2020 .

Используется совместно с предложением ROWS или RANGE для указания нижней (начальной) или верхней (конечной) граничной точки окна. Used with either ROWS or RANGE to specify the lower (starting) and upper (ending) boundary points of the window. определяет граничную начальную точку, а определяет граничную конечную точку. defines the boundary starting point and defines the boundary end point. Верхняя граница не может быть меньше нижней границы. The upper bound cannot be smaller than the lower bound.

UNBOUNDED FOLLOWING UNBOUNDED FOLLOWING
Применимо к: с SQL Server 2012 (11.x) SQL Server 2012 (11.x) до SQL Server 2020 SQL Server 2020 . Applies to: SQL Server 2012 (11.x) SQL Server 2012 (11.x) through SQL Server 2020 SQL Server 2020 .

Указывает, что окно заканчивается на последней строке секции. Specifies that the window ends at the last row of the partition. UNBOUNDED FOLLOWING может быть указано только как конечная точка окна. UNBOUNDED FOLLOWING can only be specified as a window end point. Например, RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING определяет, что окно начинается на текущей строке и заканчивается на последней строке секции. For example RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING defines a window that starts with the current row and ends with the last row of the partition.

FOLLOWING FOLLOWING
Указывается со для обозначения числа строк или значений после текущей строки. Specified with to indicate the number of rows or values to follow the current row. При указании FOLLOWING как начальной точки окна конечная точка должна быть FOLLOWING. When FOLLOWING is specified as the window starting point, the ending point must be FOLLOWING. Например, ROWS BETWEEN 2 FOLLOWING AND 10 FOLLOWING определяет, что окно начинается на второй строке после текущей и заканчивается на десятой строке после текущей строки. For example, ROWS BETWEEN 2 FOLLOWING AND 10 FOLLOWING defines a window that starts with the second row that follows the current row and ends with the tenth row that follows the current row. Эта спецификация не допускается в предложении RANGE. This specification is not allowed for RANGE.

неподписанный целочисленный литерал unsigned integer literal
Применимо к: с SQL Server 2012 (11.x) SQL Server 2012 (11.x) до SQL Server 2020 SQL Server 2020 . Applies to: SQL Server 2012 (11.x) SQL Server 2012 (11.x) through SQL Server 2020 SQL Server 2020 .

Положительный целочисленный литерал (включая 0), который указывает число строк или значений перед или после текущей строки или значения. Is a positive integer literal (including 0) that specifies the number of rows or values to precede or follow the current row or value. Эта спецификация является допустимой только в предложении ROWS. This specification is valid only for ROWS.

Общие замечания General Remarks

В одном запросе с одним предложением FROM может использоваться несколько оконных функций. More than one window function can be used in a single query with a single FROM clause. Предложение OVER для каждой функции может отличаться в части секционирования и упорядочения. The OVER clause for each function can differ in partitioning and ordering.

Если PARTITION BY не указан, функция обрабатывает все строки результирующего набора запроса как одну группу. If PARTITION BY is not specified, the function treats all rows of the query result set as a single group.

Важно! Important!

Если указано предложение ROWS или RANGE и используется для (короткий синтаксис), то данная спецификация используется в качестве начальной точки границы рамки окна, а CURRENT ROW — в качестве конечной точки границы окна. If ROWS/RANGE is specified and is used for (short syntax) then this specification is used for the window frame boundary starting point and CURRENT ROW is used for the boundary ending point. Например «ROWS 5 PRECEDING» равно «ROWS BETWEEN 5 PRECEDING AND CURRENT ROW». For example «ROWS 5 PRECEDING» is equal to «ROWS BETWEEN 5 PRECEDING AND CURRENT ROW».

Если предложение ORDER BY не указано, то для рамки окна используется весь раздел. If ORDER BY is not specified entire partition is used for a window frame. Это относится только к тем функциям, которым не требуется предложение ORDER BY. This applies only to functions that do not require ORDER BY clause. Если предложение ROWS или RANGE не указаны, а указано предложение ORDER BY, то в качестве значения по умолчанию для рамки окна используется RANGE UNBOUNDED PRECEDING AND CURRENT ROW. If ROWS/RANGE is not specified but ORDER BY is specified, RANGE UNBOUNDED PRECEDING AND CURRENT ROW is used as default for window frame. Это относится только к тем функциям, которые могут принимать дополнительную спецификацию ROWS или RANGE. This applies only to functions that have can accept optional ROWS/RANGE specification. Например, ранжирующая функция не может принимать предложение ROWS или RANGE, поэтому данная рамка окна не может использоваться, даже несмотря на наличие предложения ORDER BY, а предложение ROWS или RANGE отсутствует. For example, ranking functions cannot accept ROWS/RANGE, therefore this window frame is not applied even though ORDER BY is present and ROWS/RANGE is not.

Ограничения Limitations and Restrictions

Предложение OVER не может использоваться с агрегатной функцией CHECKSUM. The OVER clause cannot be used with the CHECKSUM aggregate function.

Предложение RANGE не может использоваться со PRECEDING или со FOLLOWING. RANGE cannot be used with PRECEDING or FOLLOWING.

В зависимости от используемой функции (ранжирующая, агрегатная или аналитическая) с предложением OVER, и (или) могут не поддерживаться. Depending on the ranking, aggregate, or analytic function used with the OVER clause, and/or the may not be supported.

Примеры Examples

A. A. Использование предложения OVER с функцией ROW_NUMBER Using the OVER clause with the ROW_NUMBER function

Следующий пример демонстрирует использование предложения OVER с функцией ROW_NUMBER для отображения номера каждой строки в секции. The following example shows using the OVER clause with ROW_NUMBER function to display a row number for each row within a partition. Предложение ORDER BY, указанное в предложении OVER упорядочивает строки каждой секции по столбцу SalesYTD . The ORDER BY clause specified in the OVER clause orders the rows in each partition by the column SalesYTD . Предложение ORDER BY в инструкции SELECT определяет порядок, в котором возвращается весь результирующий набор запроса. The ORDER BY clause in the SELECT statement determines the order in which the entire query result set is returned.

Ниже приводится результирующий набор. Here is the result set.

Б. B. Использование предложения OVER с агрегатными функциями Using the OVER clause with aggregate functions

В следующем примере предложение OVER используется с агрегатной функцией для всех возвращаемых запросом строк. The following example uses the OVER clause with aggregate functions over all rows returned by the query. В данном примере использование предложения OVER является более эффективным, чем использование вложенных запросов для получения статистических значений. In this example, using the OVER clause is more efficient than using subqueries to derive the aggregate values.

Ниже приводится результирующий набор. Here is the result set.

Следующий пример демонстрирует использование предложения OVER с агрегатной функцией в вычисляемом значении. The following example shows using the OVER clause with an aggregate function in a calculated value.

Ниже приводится результирующий набор. Here is the result set. Обратите внимание, что статистические функции вычисляются в столбце SalesOrderID , а столбец Percent by ProductID вычисляется для каждой строки каждого SalesOrderID . Notice that the aggregates are calculated by SalesOrderID and the Percent by ProductID is calculated for each line of each SalesOrderID .

В. C. Нахождение скользящей средней и кумулятивной суммы Producing a moving average and cumulative total

В следующем примере показано использование функций AVG и SUM с предложением OVER для вычисления скользящей средней и кумулятивной суммы годовых продаж по каждой территории, указанной в таблице Sales.SalesPerson . The following example uses the AVG and SUM functions with the OVER clause to provide a moving average and cumulative total of yearly sales for each territory in the Sales.SalesPerson table. Данные секционируются по TerritoryID и логически сортируются по SalesYTD . The data is partitioned by TerritoryID and logically ordered by SalesYTD . Это означает, что функция AVG вычисляется для каждой территории на основании объема продаж за год. This means that the AVG function is computed for each territory based on the sales year. Обратите внимание, что в TerritoryID 1 для продаж за 2005 год используются две строки, в которых представлены два менеджера по продажам с показателями за этот год. Notice that for TerritoryID 1, there are two rows for sales year 2005 representing the two sales people with sales that year. После расчета среднего значения продаж для двух данных строк в вычисление включается третья строка, представляющая продажи за 2006 год. The average sales for these two rows is computed and then the third row representing sales for the year 2006 is included in the computation.

Ниже приводится результирующий набор. Here is the result set.

В этом примере предложение OVER не включает в себя предложение PARTITION BY. In this example, the OVER clause does not include PARTITION BY. Это означает, что функция будет применяться для всех строк, возвращаемых запросом. This means that the function will be applied to all rows returned by the query. Предложение ORDER BY, указанное в предложении OVER, определяет логический порядок применения функции AVG. The ORDER BY clause specified in the OVER clause determines the logical order to which the AVG function is applied. Запрос возвращает скользящее среднее значение продаж за год для всех территорий, указанных в предложении WHERE. The query returns a moving average of sales by year for all sales territories specified in the WHERE clause. Предложение ORDER BY, указанное в инструкции SELECT, определяет порядок отображения строк запроса. The ORDER BY clause specified in the SELECT statement determines the order in which the rows of the query are displayed.

Ниже приводится результирующий набор. Here is the result set.

Г. D. Указание предложения ROWS Specifying the ROWS clause

Применимо к: с SQL Server 2012 (11.x) SQL Server 2012 (11.x) до SQL Server 2020 SQL Server 2020 . Applies to: SQL Server 2012 (11.x) SQL Server 2012 (11.x) through SQL Server 2020 SQL Server 2020 .

В следующем примере с помощью предложения ROWS определяется окно, в рамках которого вычисляется текущая строка, а также N последующих строк (1 строка в данном примере). The following example uses the ROWS clause to define a window over which the rows are computed as the current row and the N number of rows that follow (1 row in this example).

Ниже приводится результирующий набор. Here is the result set.

В следующем примере предложение ROWS указывается с UNBOUNDED PRECEDING. In the following example, the ROWS clause is specified with UNBOUNDED PRECEDING. В результате окно начинается с первой строки секции. The result is that the window starts at the first row of the partition.

Ниже приводится результирующий набор. Here is the result set.

Примеры: Параллельное хранилище данных Parallel Data Warehouse Examples: Параллельное хранилище данных Parallel Data Warehouse

Д. E. Использование предложения OVER с функцией ROW_NUMBER Using the OVER clause with the ROW_NUMBER function

В следующем примере возвращается ROW_NUMBER для торговых представителей в зависимости от установленной для них квоты продаж. The following example returns the ROW_NUMBER for sales representatives based on their assigned sales quota.

Здесь приводится частичный результирующий набор. Here is a partial result set.

Е. F. Использование предложения OVER с агрегатными функциями Using the OVER clause with aggregate functions

Следующие примеры демонстрируют использование предложения OVER с агрегатными функциями. The following examples show using the OVER clause with aggregate functions. В данном примере использование предложения OVER является более эффективным, чем использование вложенных запросов. In this example, using the OVER clause is more efficient than using subqueries.

Ниже приводится результирующий набор. Here is the result set.

Следующий пример демонстрирует использование предложения OVER с агрегатной функцией в вычисляемом значении. The following example shows using the OVER clause with an aggregate function in a calculated value. Обратите внимание, что статистические выражения вычисляются в столбце SalesOrderNumber , а процент от общего числа заказов на продажу вычисляется для каждой строки каждого SalesOrderNumber . Notice that the aggregates are calculated by SalesOrderNumber and the percentage of the total sales order is calculated for each line of each SalesOrderNumber .

Первый запуск этого результирующего набора: The first start of this result set is:

Конструкция WITH в T-SQL или обобщенное табличное выражение (ОТВ)

Всем привет! Тема сегодняшнего материала будет посвящена обобщенным табличным выражениям языка T-SQL, мы с Вами узнаем, что это такое, а также рассмотрим примеры написания запросов с использованием этих самых обобщённых табличных выражений.

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

Что такое обобщенное табличное выражение?

Common Table Expression (CTE) или обобщенное табличное выражение (OTB) – это временные результирующие наборы (т.е. результаты выполнения SQL запроса), которые не сохраняются в базе данных в виде объектов, но к ним можно обращаться.

Главной особенностью обобщенных табличных выражений является то, что с помощью них можно писать рекурсивные запросы, но об этом чуть ниже, а сейчас давайте поговорим о том, в каких случаях нам могут пригодиться OTB, в общем, для чего они предназначены:

  • Основной целью OTB является написание рекурсивных запросов, можно сказать для этого они, и были созданы;
  • OTB можно использовать также и для замены представлений (VIEW), например, в тех случаях, когда нет необходимости сохранять в базе SQL запрос представления, т.е. его определение;
  • Обобщенные табличные выражения повышают читаемость кода путем разделения запроса на логические блоки, и тем самым упрощают работу со сложными запросами;
  • Также OTB предназначены и для многократных ссылок на результирующий набор из одной и той же SQL инструкции.

Обобщенное табличное выражение определяется с помощью конструкции WITH, и определить его можно как в обычных запросах, так и в функциях, хранимых процедурах, триггерах и представлениях.

Синтаксис:

  • common_table_expression_name – это псевдоним или можно сказать идентификатор обобщенного табличного выражения. Обращаться к OTB мы будем, как раз используя этот псевдоним;
  • column_name – имя столбца, который будет определен в обобщенном табличном выражении. Использование повторяющихся имен нельзя, а также их количество должно совпадать с количеством столбцов возвращаемых запросом CTE_query_definition. Указывать имена столбцов необязательно, но только в том случае, если всем столбцам в запросе CTE_query_definition присвоены уникальные псевдонимы;
  • CTE_query_definition — запрос SELECT, к результирующему набору которого, мы и будем обращаться через обобщенное табличное выражение, т.е. common_table_expression_name.

После обобщенного табличного выражения, т.е. сразу за ним должен идти одиночный запрос SELECT, INSERT, UPDATE, MERGE или DELETE.

Какие бывают обобщенные табличные выражения?

Они бывают простые и рекурсивные.

Простые не включают ссылки на самого себя, а рекурсивные соответственно включают.

Рекурсивные ОТВ используются для возвращения иерархических данных, например, классика жанра это отображение сотрудников в структуре организации (чуть ниже мы это рассмотрим).

Примечание! Все примеры ниже будут рассмотрены в MS SQL Server 2008 R2.

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

    User >Как видите, у директора отсутствует ManagerID, так как у него нет начальника. А теперь переходим к примерам.

Пример простого обобщенного табличного выражения

Для примера давайте просто выведем все содержимое таблицы TestTable с использованием обобщенного табличного выражения

Где TestCTE это и есть псевдоним результирующего набора, к которому мы и обращаемся.

В данном случае мы могли и не перечислять имена столбцов, так как они у нас уникальны. Можно было просто написать вот так:

Пример рекурсивного обобщенного табличного выражения

Теперь допустим, что нам необходимо вывести иерархический список сотрудников, т.е. мы хотим видеть, на каком уровне работает тот или иной сотрудник. Для этого пишем рекурсивный запрос:

В итоге, если мы захотим, мы можем легко получить список сотрудников определенного уровня, например, нам нужны только начальники отделов, для этого мы просто в указанный выше запрос добавим условие WHERE LevelUser = 1

При написании рекурсивного ОТВ нужно быть внимательным, так как неправильное его составление может привести к бесконечному циклу. Поэтому для этих целей есть опция MAXRECURSION, которая может ограничивать количество уровней рекурсии. Давайте представим, что мы не уверены, что написали рекурсивное обобщенное выражение правильно и для отладки напишем инструкцию OPTION (MAXRECURSION 5), т.е. отобразим только 5 уровня рекурсии, и если уровней будет больше, SQL инструкция будет прервана.

Запрос у нас отработал, что говорит о том, что мы написали его правильно и соответственно OPTION (MAXRECURSION 5) можно смело убрать.

Заметка! Начинающим программистам рекомендую почитать мою книгу «Путь программиста T-SQL. Самоучитель по языку Transact-SQL», в ней я подробно, с большим количеством примеров, рассказываю про другие полезные возможности языка Transact-SQL.

Глава 2. SQL : ОБЗОР.

Глава 2. SQL : ОБЗОР.

ЭТА ГЛАВА ПОЗАКОМИТ ВАС СО СТРУКТУРОЙ SQL языка а также с определенными общими выводами, такими как тип данных которые эти поля могут содержать и некоторые области неоднозначностей которые существуют в SQL.

Она педназначена обеспечить связь с более конкретной информацией в последующих главах. Вы не должны запоминать каждую подробность упомянутую в этой главе. Краткий обзор представлен здесь в одной удобно размещеной области, многие подробности которой вы можете иметь чтобы в последствии ссылаться к ним по мере овладения языком. Мы поместили все это в начало книги чтобы ориентировать вас на мир SQL без упрощенного подхода к его проблемам и в тоже время дать Вам привычные в будущем места для ссылки к ним когда у Вас появятся вопросы. Этот материал может стать более понятным когда мы перейдем к описанию конкретных команд SQL, начинающихся с Главы 3.

КАК РАБОТАЕТ SQL?

SQL это язык ориентированный специально на реляционные базы данных.

Он устраняет много работы которую вы должны были бы сделать если бы вы использовали универсальный язык программирования, напрмер C. Чтобы сформировать реляционную базу данных на C, вам необходимо было бы начать с самого начала. Вы должны были бы определить объект — называемый таблицей которая могла бы расти чтобы иметь любое число строк, а затем создавать постепенно процедуры для помещения значений в нее и извлечения из них. Если бы вы захотели найти некоторые определенные строки, вам необходимо было бы выполнить по шагам процедуру, подобную следующей :

* Рассмотрите строку таблицы.


* Выполните проверку — является ли эта строка одной из строк которая вам нужна.

* Если это так, сохраните ее где-нибудь пока вся таблица не будет проверена.

* Проверьте имеются ли другие строки в таблице.

* Если имеются, возвратитесь на шаг 1.

* Если строк больше нет, вывести все значения сохраненные в шаге 3.

( Конечно, это не фактический набор C команд, а только логика шагов которые должны были бы быть включены в реальную программу.) SQL сэкономит вам все это. Команды в SQL могут работать со всеми группами таблиц как с единым объектом и могут обрабатывать любое количество информации извлеченной или полученной из их, в виде единого модуля.

ЧТО ДЕЛАЕТ ANSI?

Как мы уже рассказывали в Введении, стандарт SQL определяется с помощью кода ANSI (Американский Национальный Институт Стандартов). ANSI не изобретал SQL. Это по существу изобретение IBM. Но другие компании подхватили SQL сразу же, по крайней мере одна компания (Oracle) отбила у IBM право на рыночную продажу SQL продуктов.

После того как появился ряд конкурирующих программ SQL на рынке, ANSI определил стандарт к которому они должны быть приведены (определение таких стандартов и является функцией ANSI ).

Однако после этого, появились некоторые проблемы. Возникли они в результате стандартизации ANSI ввиде некоторых ограничений. Так как не всегда ANSI определяет то что является наиболее полезным, то программы пытаются соответствовать стандарту ANSI не позволяя ему ограничивать их слишком сильно. Это, в свою очередь, ведет к случайным несогласованностям. Программы Баз Данных обычно дают ANSI SQL дополнительные особенности и часто ослабляют многие ограничения из большинства из них.

Следовательно, общие разновидности ANSI будут также рассмотрены. Хотя мы очевидно не сможем объять каждое исключение или разновидность, удачные идеи имеют тенденцию к внедрению и использованию в различных программах даже когда они не определены стандартом ANSI.

ANSI — это вид минимального стандарта и вы можете делать больше чем он позволяет, хотя и должны выполнять его указания при выполнении задач которые он определяет.

ИНТЕРАКТИВНЫЙ И ВЛОЖЕННЫЙ SQL

Имеются два SQL: Интерактивный и Вложенный. Большей частью, обе формы работают одинаково, но используются различно. Интерактивный SQL используется для функционирования непосредственно в базе данных чтобы производить вывод для использования его заказчиком. В этой форме SQL, когда вы введете команду, она сейчас же выполнится и вы сможете увидеть вывод (если он вообще получится) — немедленно.

Вложенный SQL состоит из команд SQL помещенных внутри программ, которые обычно написаны на некотором другом языке (типа КОБОЛА или Паскаля).

Это делает эти программы более мощными и эффективным. Однако, допуская эти языки, приходится иметь дело с структурой SQL и стилем управления данных который требует некоторых расширений к интерактивному SQL. Передача SQL команд во вложенный SQL является выдаваемой («passed off») для переменных или параметров используемых программой в которую они были вложены.

В этой книге, мы будем представлять SQL в интерактивной форме. Это даст нам возможность обсуждать команды и их эффекты не заботясь о том как они связаны с помощью интерфейса с другими языками. Интерактивный SQL — это форма наиболее полезная непрограммистам. Все что вы узнаете относительно интерактивного SQL в основном применимо и к вложенной форме. Изменения необходимые для использования вложенной формы будут использованы в последней главе этой книги.

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

К сожалению, эти термины не используются повсеместно во всех реализациях. Они подчеркиваются ANSI и полезны на концептуальном уровне, но большинство SQL программ практически не обрабатывают их отдельно, так что они по существу становятся функциональными категориями команд SQL.

DDL (Язык Определения Данных ) — так называемый Язык Описания Схемы в ANSI, состоит из команд которые создают объекты (таблицы, индексы, просмотры, и так далее ) в базе данных.

DML (Язык Манипулирования Данными) — это набор команд которые определяют какие значения представлены в таблицах в любой момент времени.

DCD (Язык Управления Данными) состоит из средств которые определяют, разрешить ли пользователю выполнять определенные действия или нет.

Они являются составными частями DDL в ANSI. Не забывайте эти имена.

Это не различные языки, а разделы команд SQL сгруппированных по их функциям.

РАЗЛИЧНЫЕ ТИПЫ ДАННЫХ

Не все типы значений которые могут занимать поля таблицы — логически одинаковые. Наиболее очевидное различие — между числами и текстом. Вы не можете помещать числа в алфавитном порядке или вычитать одно имя из другого. Так как системы с реляционной базой данных базируются на связях между фрагментами информации, различные типы данных должны понятно отличаться друга от друга, так чтобы соответствующие процессы и срав нения. могли быть в них выполнены.

В SQL, это делается с помощью назначения каждому полю — типа данных который укаазывает на тип значения которое это поле может содержать.

Все значения в данном поле должны иметь одинаковый тип. В таблице Заказчиков, например, cname и city — содержат строки текста для оценки, snum, и cnum — это уже номера. По этой причине, вы не можете ввести значение Highest(Наивысший) или значение None(Никакой) в поле rating, которое имеет числовой тип данных. Это ограничение удачно, так как оно налагает некоторую структурность на ваши данные. Вы часто будете сравнивать некоторые или все значения в данном поле, поэтому вы можете выполнять действие только на определенных строках а не на всех. Вы не могли бы сделать этого если бы значения полей имели смешанный тип данных.

К сожалению, определение этих типов данных является основной областью в которой большинство коммерческих программ баз данных и официальный стандарт SQL, не всегда совпадают. ANSI SQL стандарт распознает только текст и тип номера, в то время как большинство коммерческих программ используют другие специальные типы. Такие как, DATA(ДАТА) и TIME(ВРЕМЯ) — фактически почти стандартные типы( хотя точный формат их меняется). Некоторые пакеты также поддерживают такие типы, как например MONEY(ДЕНЬГИ) и BINARY (ДВОИЧНЫЕ). (MONEY — это специальная система исчисления используемая компьютерами. Вся информация в компьютере передается двоичными числами и затем преобразовываются в другие системы, что бы мы могли легко использовать их и понимать.)

ANSI определяет несколько различных типов значений чисел, различия между которыми — довольно тонки и иногда их путают. Разрешенные ANSI типы данных перечислены в Приложении B.

Сложность числовых типов ANSI можно, по крайней мере частично,объяснить усилием сделать вложенный SQL, совместимым с рядом других языков.

Два типа чисел ANSI, INTEGER(ЦЕЛОЕ ЧИСЛО) и DECIMAL (ДЕСЯТИЧНОЕ ЧИСЛО) (которые можно сокращать как INT и DEC, соответственно ), будут адекватны для наших целей, также как и для целей большинства практических деловых прикладных программ. Естественно, что тип ЦЕЛОЕ можно представить как ДЕСЯТИЧНОЕ ЧИСЛО которое не содержит никаких цифр справа от десятичной точки.

Тип для текста — CHAR (или СИМВОЛ ), который относится к строке текста. Поле типа CHAR имеет определенную длину, которая определяется максимальным числом символов которые могут быть введены в это поле.

Больше всего реализаций также имеют нестандартный тип называемый VARCHAR(ПЕРЕМЕННОЕ ЧИСЛО СИМВОЛОВ), который является текстовой строкой которая может иметь любую длину до определенного реализацией максимума (обычно 254 символа). CHARACTER и VARCHAR значения включаются в одиночные кавычки как «текст». Различие между CHAR и VARCHAR в том, что CHAR должен резервировать достаточное количество памяти для максимальной длины строки, а VARCHAR распределяет память так как это необходимо.

Илон Маск рекомендует:  Краткое описание процессоров AMD Vishera, отзывы покупателей

Символьные типы состоят из всех печатных символов, включая числа.

Однако, номер 1 не то же что символ «1». Символ «1» — только другой печатный фрагмент текста, не определяемый системой как наличие числового значения 1.

Например 1 + 1=2, но «1» + «1» не равняется «2».

Символьные значения сохраняются в компьютере как двоичные значения, но показываются пользователю как печатный текст. Преобразование следует за форматом определяемым системой которую вы используете. Этот формат преобразования будет одним из двух стандартных типов (возможно с расширениями) используемых в компьютерных системах: в ASCII коде (используемом во всех персональных и малых компьютерах ) и EBCDIC коде (Расширенном Двоично-Десятичном Коде Объмена Информации) (используемом в больших компьютерах). Определенные операции, такие как упорядочивание в алфавитном порядке значений поля, будет изменяться вместе с форматом. Применение этих двух форматов будет обсуждаться в Главе 4.

Мы должны следить за рынком, а не ANSI, в использовании типа называемого DATE(ДАТОЙ). (В системе, которая не распознает тип ДАТА, вы конечно можете обьявить дату как символьное или числовое поле, но это сделает большинство операций более трудоемкими. ) Вы должны смотреть свою документацию по пакету программ которые вы будете использовать, чтобы выяснить точно, какие типы данных она поддерживает.

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

ЧТО ТАКОЕ — ПОЛЬЗОВАТЕЛЬ?

SQL обычно находится в компьютерных системах которые имеют больше чем одного пользователя, и следовательно должны делать различие между ними (ваше семейство PC может иметь любое число пользователей, но оно обычно не имеет способов чтобы отличвать одного от другого). Обычно, в такой системе, каждый пользователь имеет некий вид кода проверки прав который идентифицирует его или ее (терминология изменяется). В начале сеанса с компьютером, пользователь входит в систему (регистрируется), сообщая компьютеру кто этот пользователь, идентифицированный с помощью определенного ID(Идентификатора). Любое колличество людей использующих тот же самый ID доступа, являются отдельными пользователями; и аналогично, один человек может представлять большое количество пользователей (в разное время ), используя различные доступные Идентификаторы.

SQL следует этому примеру. Действия в большинстве сред SQL приведены к специальному доступному Идентификатору который точно соответствует определенному пользователю. Таблица или другой объект принадлежит пользователю, который имеет над ним полную власть. Пользователь может или не может иметь привилегии чтобы выполнять действие над объектом.

Для наших целей, мы договоримся, что любой пользователь имеет привилегии необходимые чтобы выполнять любое действие, пока мы не возвратимся специально к обсуждению привилегий в Главе 22.

Специальное значение — USER(ПОЛЬЗОВАТЕЛЬ) может использоваться как аргумент в команде. Оно указывает на доступный Идентификатор пользователя, выдавшего команду.

УСЛОВИЯ И ТЕРМИНОЛОГИЯ

Ключевые слова — это слова которые имеют специальное значение в SQL. Они могут быть командами, но не текстом и не именами объектов. Мы будем выделять ключевые слова печатая их ЗАГЛАВНЫМИ БУКВАМИ. Вы должны соблюдать осторожность чтобы не путать ключевые слова с терминами.

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

Команды, или предложения, являются инструкциями которыми Вы обращаетесь к SQL базе данных. Команды состоят из одной или более отдельных логических частей называемых предложениями. Предложения начинаются ключевым словом для которого они являются проименованными, и состоят из ключевых слов и аргументов. Например предложения с которыми вы можете сталкиваться — это » FROM Salespeope » и » WHERE city=»London».

Аргументы завершают или изменяют значение предложения. В примерах выше, Salespeople — аргумент, а FROM — ключевое слово предложения FROM.

Аналогично, » city=»London» » — агрумент предложения WHERE. Объекты — структуры в базе данных которым даны имена и сохраняются в памяти.

Они включают в себя базовые таблицы, представления (два типа таблиц), и индексы.

Чтобы показать Вам как формируются команды, мы будем делать это на примерах. Имеется, однако, более формальный метод описания команд использующих стандартизированные условные обозначения. Мы будем использовать его в более поздних главах, для удобства чтобы понимать эти условные обозначения в случае если вы столкнетесь с ним в других SQL документах. Квадратные скобки ([ ] ) будут указывать части которые могут неиспользоваться, а многоточия (. ) указывать что все предшествующее им может повторяться любое число раз. Слова обозначенные в угловых скобках (<>) — специальные термины которые объясняют что они собой представляют.

Мы упростили стандартную терминологию SQL значительно, но без ухудшения его понимания.

Мы быстро прошли основы в этой главе. Но нашим намерением и было — просто пролететь над основами SQL, так чтобы вы могли понять идею относительно всего объема. Когда мы возвратимся к основе в следующей главе, некоторые вещи станут более конкретными. Теперь вы знаете кое-что относительно SQL — какова его структура, как он используется, как он представляет данные, и как они определяются (и некоторые несогласованности появляющиеся при этом ), и некоторые условные обозначения и термины используемые чтобы описывать их. Все это — много информации для одной главы; мы не ожидаем что бы вы запомнили все эти подробности, но вы сможете вернуться позже к ним если понадобится. По Главе 3, мы будем идти, показывая конкретно, как формируются команды и что они делают. Мы представим вам команду SQL используемую чтобы извлекать информацию из таблиц, и которая является наиболее широко используемой командой в SQL. К концу этой главы, вы будете способны извлекать конкретную информацию из вашей базы данных с высокой степенью точности.

10 простых шагов к полному пониманию SQL

Очень многие программисты смотрят на SQL, как на страшного зверя. SQL — один из немногих декларативных языков, и его поведение в корне отличается от того, как работают императивные, объектно-ориентированные и даже функциональные языки программирования. Хотя многие рассматривают SQL в некоторой степени функциональным.

Поэтому я чувствую себя обязанным донести прелести SQL до умов тех, кто все еще испытывает трудности с его пониманием. Этот урок посвящен тем, кто:

  • Уже работает с SQL, но не до конца его понимает
  • Неплохо знает SQL, но никогда серьезно не задумывался над его структурой
  • Хочет обучать SQL других

В этом руководстве мы сосредоточимся только на операторах SELECT. Другие DML-операторы будут подробно рассмотрены в следующий раз.


Примечание. Этот урок раньше публиковался только на
Tech.Pro (оригинальная версия находится здесь). К сожалению, материал Tech.Pro стал недоступным. С разрешения Tech.Pro мы снова публикуем его контент в блоге jOOQ.

SQL является декларативным

Все понятно. И вас не волнует, откуда эти записи о сотруднике (employee) берутся. Вам лишь нужны те, у которых достойная зарплата (salary).

  • Что мы из этого узнаем?

Если все так просто, в чем же проблема? Проблема в том, что большинство из нас интуитивно мыслит рамками императивного программирования. Вроде: «машина, сделай это, затем то, но сначала проверь то и се.» А значит, нужно хранить временные результаты в переменных, составлять циклы, вызывать функции и т. д. и т. п.

Забудьте обо всем этом. Думайте о том, как объявлять вещи. Не о том, как сказать машине, вычислить что-либо.

2. Код SQL не является упорядоченным

Обычно путаница происходит из-за того, что элементы кода SQL не расположены в том порядке, в каком они выполняются. Лексический порядок выглядит так:

  • SELECT [ DISTINCT ]
  • FROM
  • WHERE
  • GROUP BY
  • HAVING
  • UNION
  • ORDER BY

Для простоты перечислены не все предложения SQL. Этот словесный порядок принципиально отличается от логического порядка (который в свою очередь может отличаться от порядка выполнения в зависимости от выбора оптимизатора):

Три пункта, которые следует отметить:

  1. Первое предложение здесь FROM, а не SELECT. Сначала происходит загрузка данных с диска в память, чтобы с ними можно было работать.
  2. SELECT выполняется после большинства других предложений. Главное, после FROM и GROUP BY. Это важно понимать, если думаете, что можете ссылаться на элементы, которые объявляете в предложении SELECT из предложения WHERE. Следующее невозможно:

Есть два варианта повторно использовать z. Либо повторить выражение:

… либо прибегнуть к производным таблицам, общим табличным выражениям или представлениям данных, чтобы избежать повторения кода. Смотрите примеры ниже.

3. UNION ставится перед ORDER BY в лексическом и логическом порядках. Многие думают, что каждый подзапрос UNION можно упорядочить, но по стандарту SQL и в большинстве диалектов SQL это не так. Хотя в некоторых диалектах позволяется упорядочивание подзапросов или производных таблиц, нет никакой гарантии, что такой порядок будет сохранен после выполнения операции UNION.

Обратите внимание, что не все базы данных реализуют вещи одинаковым образом. Правило номер 2, например, не применяется в точности, как описано выше, для MySQL, PostgreSQL, и SQLite.

Что мы из этого узнаем?

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

Конечно, неплохо, если бы язык был спроектирован таким образом, когда лексическая последовательность фактически отражает логический порядок, как это реализовано в Microsoft LINQ.

3. Вся суть SQL заключается в ссылках на таблицы

Из-за разницы между лексическим упорядочением и логическим упорядочением большинство новичков, вероятно, думают, что значения столбцов являются объектами первого класса в SQL. Но, нет. Наиболее важными являются ссылки на таблицы.

Стандарт SQL определяет предложение FROM следующим образом:

Вывод предложения FROM — это объединенная ссылка на таблицу объединенного значения всех ссылок. Попробуем это переварить.

Указанная выше запись производит комбинированную ссылку на таблицу значений a и b. Если a имеет 3 колонки и b 5 колонок, тогда выходная таблица “output table” будет состоять из 8 (3 + 5) столбцов.

Записи, содержащиеся в этой комбинированной табличной ссылке являются перекрестным / декартовым произведением a x b. Иными словами, каждая запись a образует пару с записью b. Если a имеет 3 записи, а b 5 записей, описанная выше ссылка на таблицу производит 15 записей (3 x 5).


Этот вывод переводится в предложение GROUP BY (после фильтрации в предложении WHERE), где преобразуется в новый вывод. Разберемся с этим позже.

Если мы посмотрим на эти примеры в свете реляционной алгебры / теории множества, то таблица SQL — это отношение или набор кортежей. Каждое предложение SQL преобразует одно или несколько отношений, чтобы создать новые отношения.

Что мы из этого узнаем?

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

4. Ссылки на таблицы SQL могут быть довольно функциональными

Ссылка на таблицу — мощная штука. Примером их силы является ключевое слово JOIN, которое в действительности не является выражением SELECT, а частью специальной ссылки на таблицу. Объединенная таблица, как определено в стандарте SQL (упрощенный):

Вернемся к нашему примеру:

a может по сути быть объединенной таблицей:

Развивая предыдущее выражение, получим:

Хотя не рекомендуется объединять синтаксис, где приводится разделенный запятыми список ссылок на таблицы, с синтаксисом объединенных таблиц, но так можно делать. В результате, объединенная ссылка будет содержать величины a1+a2+b.

Производные таблицы еще мощнее, чем объединенные таблицы. Мы до этого еще дойдем.

Что мы из этого узнаем?

Всегда нужно думать категориями ссылок на таблицы. Это поможет не только понять, как данные переходят в предложениях SQL, (смотрите предыдущий раздел), но и как создаются сложные ссылки на таблицы.

И, что важно, понять, JOIN является ключевым словом для построения соединенных таблиц. А не частью оператора SELECT. Некоторые базы данных позволяют использование JOIN в операторах INSERT, UPDATE, DELETE

5. В SQL следует использовать таблицы JOIN, вместо разделенных запятыми

Ранее мы видели это предложение:

Продвинутые разработчики SQL, вероятно, скажут, что не следует вообще использовать список с разделителями-запятыми, и всегда отображать таблицы JOIN. Это улучшит читаемость инструкции SQL, и тем самым предотвратить ошибки.

Одна очень распространенная ошибка заключается в том, чтобы где-то забыть предикат JOIN. Подумайте о следующем:

Синтаксис соединенных таблиц:

  • Безопаснее, так как предикаты join можно размещать вблизи соединенных таблиц, тем самым предотвращая ошибки.
  • Более выразительные, так как можно различать OUTER JOIN, INNER JOIN и т. д.

Что мы из этого узнаем?

Всегда применяйте JOIN. Никогда не используйте ссылки на таблицы, разделенные запятыми, в предложениях FROM.

6. Различные операции JOIN в SQL

Операции JOIN состоят, в основном, из следующих пяти видов:

  • EQUI JOIN
  • SEMI JOIN
  • ANTI JOIN
  • CROSS JOIN
  • DIVISION

Эти термины обычно используются в реляционной алгебре. SQL задействует другие термины для вышеуказанных понятий, если они вообще существуют. Давайте рассмотрим их поближе:

EQUI JOIN

Это наиболее распространенная операция JOIN. Содержит два подвида:

  • INNER JOIN (или просто JOIN)
  • OUTER JOIN (далее подразделяется на LEFT, RIGHT, FULL OUTER JOIN)

Разницу лучше объяснить на примере:

SEMI JOIN

Эта реляционная концепция в SQL может быть выражена двумя способами: С помощью предиката IN или с использованием предиката EXISTS. «Semi» на латыни означает «половина». Этот тип соединения используется для объединения только «половины» ссылки на таблицу. Что это значит? Рассмотрим вновь вышеуказанное объединение автора и книги. Представим, что нам не нужны комбинации автор — книга, а только авторы, у которых есть книги. Тогда можно написать:

Хотя нет общего правила, следует предпочесть IN или EXISTS, но можно сказать примерно так:

  • Предикаты IN легче читать, чем предикаты EXISTS
  • Предикаты EXISTS более выразительные, чем предикаты IN (т. е. их проще выразить, чем сложные предикаты SEMI JOIN)
  • В производительности нет какой-либо заметной разницы. Но большая разница в производительности может быть в некоторых базах данных.

Поскольку INNER JOIN также выдают результаты авторов, у которых есть книги, многие начинающие подумают, что можно удалить дубликаты с помощью ключевого слова DISTINCT. Им кажется, что SEMI JOIN можно выразить следующим образом:

Так делать не рекомендуется по двум причинам:

  • Замедляется производительность, так как база данных только для того, чтобы удалить дубликаты, должна загрузить в память множество данных.
  • Такой способ решения не совсем правильный, хотя и приводит к верным результатам в этом примере. Но если вы соединяете больше ссылок на таблицы, удаление дубликатов превращается в реальную проблему.

Подробную информацию о злоупотреблении DISTINCT можно найти в этом посте.

ANTI JOIN

Эта реляционная концепция является полной противоположностью SEMI JOIN. Ее можно образовать, просто добавив ключевое слово NOT в предикатах IN или EXISTS. Пример, где мы выберем тех авторов, у которых нет книг:

Применяются те же правила в отношении производительности, читаемости и выразительности. Однако есть небольшой нюанс в отношении NULL при использовании NOT IN, но эта тема выходит за рамки нашего урока.

CROSS JOIN

Этот оператор создает перекрестное произведение двух соединенных ссылок на таблицу, комбинируя каждую запись первой ссылки с записью второй ссылки на таблицу. Мы уже видели раньше, что это может быть достигнуто посредством ссылок на таблицы с разделителями-запятыми в предложении FROM. В редких случаях, когда это действительно необходимо, в большинстве диалектов SQL перекрестное соединение CROSS JOIN можно написать явным образом:

DIVISION

Реляционное деление — вот кто настоящий зверь. В кратце, если JOIN это умножение, division (деление) — противоположность операции JOIN. Реляционные деления очень трудно выразить в SQL. Поскольку этот урок для начинающих, деление мы не рассматриваем. Для самых храбрых информация находится здесь, здесь и здесь.

Что мы из этого узнаем?

Много чего. Давайте запихнем это в наши головы. В SQL повсюду ссылки на таблицы. Соединяемые таблицы представляют собой довольно сложные ссылки на таблицы. Но между реляционными выражениями и выражениями SQL есть разница. Не все операции реляционного соединения также являются формальными операциями соединения SQL. Имея немного практики и знаний в реляционной теории, вы всегда сможете выбрать верный тип реляционного соединения JOIN и правильно представить его на языке SQL.

7. Производные таблицы SQL похожи на табличные переменные

Раньше мы узнали, что SQL является декларативным языком, и не имеет переменных (хотя в некоторых диалектах SQL они существуют). Но можно написать нечто похожее на переменные. Эти звери называются производными таблицами.

Производная таблица — это не что иное, как вложенный запрос, заключенный в круглые скобки.

Обратите внимание, что некоторые диалекты SQL требуют, чтобы производные таблицы имели корреляционное имя (также называемое псевдонимом).

Производные таблицы великолепны, если необходимо обойти проблемы, вызванные логическим упорядочением предложений SQL. Например, если вы хотите повторно использовать выражение столбца в предложении SELECT и WHERE, просто напишите (диалект Oracle):

Обратите внимание, что некоторые базы данных и стандарт SQL:1999 подняли производные таблицы на следующий уровень введением обобщенных табличных выражений. Это позволит повторно использовать одну и ту же производную таблицу несколько раз в одной инструкции SQL SELECT. Приведенный выше запрос будет переведен на (почти) эквивалент:

Очевидно, что «a» можно также вывести в отдельное представление для более широкого использования общих подзапросов SQL. Подробнее о представлениях здесь.

Что мы из этого узнаем?

Снова, снова и снова. В SQL все завязано на ссылках, а не столбцах. Как этим воспользоваться. Не бойтесь написания производных таблиц или других сложных ссылок на таблицы.

8. SQL GROUP BY преобразует прежние ссылки на таблицу

Давайте вновь обсудим наше предложение FROM:

А теперь к соединенной ссылке (см. выше) применим предложение GROUP BY

Предложение производит новую ссылку на таблицу только с тремя оставшимися столбцами (!). Попробуем это переварить. С применением GROUP BY, уменьшается число доступных столбцов во всех последующих логических предложениях, включая SELECT. Ссылаться только на столбцы из предложения GROUP BY в предложении SELECT можно по синтаксической причине.

  • Обратите внимание, что другие столбцы могут по-прежнему быть доступными в качестве аргументов агрегатных функций:
  • Следует заметить, что MySQL, к сожалению, не придерживается этого стандарта, отчего получается только путаница. Не попадайтесь на уловки в MySQL. GROUP BY преобразует ссылки на таблицу Таким образом, можно ссылаться только на столбцы, также упоминаемые в предложении GROUP BY.

Что мы из этого узнаем?

GROUP BY, опять же, работает с табличными ссылками, преобразовывая их в новую форму.

9. SQL SELECT в реляционной алгебре называется проекцией

Мне лично нравится термин «проекция», так как он используется в реляционной алгебре. После того как вы создали ссылку на таблицу, отфильтровали и преобразовали ее, можете переходить к проецированию в другую форму. Предложение SELECT подобно проектору. Табличная функция использующет выражение значения строки для преобразования каждой записи из ранее созданной ссылки на таблицу в конечный результат.

В предложении SELECT можно работать со столбцами, создавая сложные выражения столбцов как части записи/строки.

Есть много специальных правил в отношении характера доступных выражений, функций и т.д. Главное, нужно помнить следующее:

  1. Можно использовать только ссылки на столбцы, полученные из ссылки на таблицу в «output».
  2. Если у вас есть предложение GROUP BY, вы можете ссылаться только на столбцы из этого предложения или агрегатные функции.
  3. Если нет предложения GROUP BY вместо агрегатных можно использовать оконные функции.
  4. Если нет предложения GROUP BY, нельзя сочетать агрегатные и неагрегатные функции.
  5. Существуют некоторые правила, касающиеся переноса регулярных функций в агрегатные функции и наоборот.
  6. Есть…

Много сложных правил. Которыми можно заполнить еще один урок. Например, причина почему нельзя комбинировать агрегатные функции с неагрегатными функциями в проекции инструкции SELECT без предложения GROUP BY (правило № 4), такова:

  1. Это не имеет смысла. Интуитивно.
  2. Если не помогает интуиция (например, новичкам в SQL), выручают синтаксические правила. В SQL:1999 реализован оператор GROUPING SETS, а в SQL:2003 — пустой оператор grouping sets: GROUP BY (). Всякий раз, когда присутствует агрегатная функция и нет явного предложения GROUP BY, применяется неявный пустой GROUPING SET (правило №2). Следовательно, исходные правила о логическом упорядочении больше не являются верными, и проекция (SELECT) влияет на результат логически предшествующего, но лексически последовательного предложения (GROUP BY).

Запутались? Да. Я тоже. Давайте вернемся к более простым вещам.

Что мы из этого узнаем?

Предложение SELECT может быть одним из самых сложных предложений в SQL, даже если оно выглядит просто. Все другие предложения только переносят ссылки на таблицы от одного к другому. Предложение SELECT портит всю красоту этих ссылок, полностью их преобразовывая путем применения к ним правил.

Чтобы понять SQL, перед использованием оператора SELECT нужно усвоить все остальное. Даже если SELECT является первым предложением в лексической упорядоченности, он должен быть последним.

10. SQL DISTINCT, UNION, ORDER BY и OFFSET — намного проще

После сложного SELECT мы можем снова вернуться к простым истинам:

  • Операции Set (DISTINCT и UNION)
  • Операции упорядочивания (ORDER BY, OFFSET .. FETCH)

Операции Set

Операции set работают с наборами, которые на самом деле являются таблицами. Почти. Теоретически, это несложно понять.


  • DISTINCT удаляет дубликаты после проекции.
  • UNION объединяет два подзапроса и удаляет дубликаты
  • UNION ALL объединяет два подзапроса, сохраняя дубликаты
  • EXCEPT удаляет записи из первого подзапроса, которые также содержатся во втором подзапросе (и затем удаляет дубликаты)
  • INTERSECT сохраняет только записи, содержащиеся в обоих поздапросах (а затем удаляет дубликаты)

Удаление дубликатов во всех этих случаях не имеет смысла. Для объединения подзапросов чаще всего следует применять UNION ALL.

Операции упорядочивания

Упорядочение не является реляционной функцией. Это функция, предназначенная только для SQL. Она применяется в самом конце лексического упорядочения и логического упорядочения инструкции SQL. Использование ORDER BY и OFFSET.. FETCH — это единственный способ гарантировать, что записи могут быть доступны по индексу надежным способом. Все остальные способы упорядочивания всегда произвольны и случайны, даже если они могут показаться воспроизводимыми.

OFFSET .. FETCH — это только один вариант синтаксиса. Другие варианты включают LIMIT, OFFSET в MySQL и PostgreSQL .. или TOP и START AT в SQL Server и Sybase. Хороший обзор различных способов реализации OFFSET.. FETCH можно увидеть здесь.

Приступаем к работе

Как и в каждом языке, чтобы освоить SQL, требуется практика. 10 вышеупомянутых простых шагов помогут вам понять обычные операции SQL. С другой стороны, неплохо учиться также на распространенных ошибках.

Запросы к оконным функциям T-SQL

Оконные функции поддерживаются не во всех элементах запросов, а только в предложениях SELECT и ORDER BY. Чтобы вы поняли причину такого ограничения, я сначала объясню принцип, который называется логической обработкой запроса. После этого я вернусь к инструкциям, которые поддерживают оконные функции, и в конце объясню, как обойти это ограничение в других предложениях.

Логическая обработка запросов

Логическая обработка запросов описывает принципы оценки запроса SELECT в соответствии с логической системой языка. Она описывает процесс, состоящий из нескольких этапов, или фаз, которые начинаются входными таблицами запроса и заканчиваются результирующим набором запроса.

Заметьте, что под логической обработкой запросов я подразумеваю концепцию оценки запроса, которая не обязательно совпадает с физическим процессом обработки запроса сервером SQL Server. В рамках оптимизации SQL Server может сокращать путь, менять порядок некоторых этапов и делать все, что ему заблагорассудится. Но все это только при условии, что он возвращает тот же результат, который должен получиться при логической обработке запроса при декларативном его определении.

Каждый этап логической обработки запроса работает с одной или несколькими таблицами (наборами строк), которые являются входными данными, и возвращает в качестве результата таблицу. Результирующая таблица одного этапа становится входной для следующего этапа.

На следующем рисунке представлена схема логической обработки запроса в SQL Server 2012:

Заметьте, что при написании запроса предложение SELECT всегда пишется первым, но в процессе логической обработки оно находится практически в самом конце — непосредственно перед обработкой предложения ORDER BY.

Логической обработке запросов можно посвятить целую книгу, но для нашей цели достаточно более лаконичного изложения. Для целей нашей дискуссии важно заметить порядок, в которой обрабатываются разные предложения. Следующий список представляет этот порядок (фазы, в которых разрешены оконные функции, выделены цветом):

Запросы sql

1. Выбрать сотрудников, фамилии которых содержат буквы ‘е’ и ‘а’
2. Выбрать последних трёх сотрудников из списка, упорядоченного по фамилии
3. Выбрать сотрудников с 3 по 5 из списка, упорядоченного по фамилии по алфавиту
4. Получить список сотрудников, которые достигнут пенсионного возраста (женщины- 55лет, мужчины -60 лет в текущем году в виде: назв.подразделения ФИО пол должность возраст дата рождения Список отсортировать по назв.подразделения
5. Создать представление, в котором выводится общая сумма окладов по каждому подразделению, если эта сумма превышает 20000 руб
6. Создать представление, в котором выводятся названия подразделений и количество служащих по каждому подразделению, если это количество превышает 5 человек
7. Создать запрос для вывода фамилии и даты приёма каждого служащего, работающего в одном подразделении со служащим заданным номером. Исключите из списка фамилию служащего заданным номером
8. Напечатать названия подразделений, в которых количество мужчин больше количества женщин

это устное задание неважно какая структура данных

пример
use Pr_r_2
go
select top 3 * from Сотрудники
order by Дата_рождения desc
go

29.03.2014, 11:39

SQL Запросы. MS SQL. 3. Приложения, которые работают со всеми серверами БД
Всем доброго времени суток! Есть задача: Приложения, которые работают со всеми серверами БД. .

Sql запросы [ms sql server 2008 r2]
Собсна, рубежный контроль, домашний, базу создал, таблицы связал, с запросами морока осталась.

SQL запросы
Задание: Для пятого по счету пассажира из числа вылетевших из Ростова в апреле 2003 года.

Sql — запросы
Помогите пожалуйста составить sql запросы БД Библиотека.

sql запросы
нужно сделать 4 запроса по таблицам и формулировки к этим запросам: Сотрудники фио должность.

Упражнения по SQL

четверг, 23 февраля 2020 г.

SELECT (обучающий этап) задачи по SQL запросам

Задачи по SQL запросам

SELECT model, speed, hd FROM PC WHERE price Задание: 2 (Serge I: 2002-09-21)

SELECT maker FROM Product WHERE type = ‘Printer’ GROUP BY maker

SELECT model,ram,screen FROM Laptop WHERE price > 1000

SELECT * FROM Printer WHERE color = ‘y’

SELECT model,speed,hd FROM PC WHERE ( cd = ’12x’ OR cd = ’24x’ ) AND price Для каждого производителя, выпускающего ПК-блокноты c объёмом жесткого диска не менее 10 Гбайт, найти скорости таких ПК-блокнотов. Вывод: производитель, скорость.

SELECT DISTINCT p.maker, l.speed
FROM laptop l
JOIN product p ON p.model = l.model
WHERE l.hd >= 10

SELECT DISTINCT product.model, pc.price
FROM Product JOIN pc ON product.model = pc.model WHERE maker = ‘B’
UNION
SELECT DISTINCT product.model, laptop.price
FROM product JOIN laptop ON product.model=laptop.model WHERE maker=’B’
UNION
SELECT DISTINCT product.model, printer.price
FROM product JOIN printer ON product.model=printer.model WHERE maker=’B’;

SELECT DISTINCT maker
FROM product
WHERE type = ‘pc’
EXCEPT
SELECT DISTINCT product.maker
FROM product
Where type = ‘laptop’

SELECT DISTINCT product.maker
FROM pc
INNER JOIN product ON pc.model = product.model
WHERE pc.speed >= 450

SELECT model, price
FROM printer
WHERE price =
(SELECT MAX(price)
FROM printer )

SELECT AVG(speed)
FROM laptop
WHERE price > 1000

SELECT AVG(pc.speed)
FROM pc, product
WHERE pc.model = product.model AND product.maker = ‘A’

SELECT maker, MAX(type)
FROM product
GROUP BY maker
HAVING COUNT(DISTINCT type) = 1 AND COUNT(model) > 1

SELECT hd FROM pc GROUP BY (hd) HAVING COUNT(model) >= 2

SELECT DISTINCT p1.model, p2.model, p1.speed, p1.ram
FROM pc p1, pc p2
WHERE p1.speed = p2.speed AND p1.ram = p2.ram AND p1.model > p2.model

select distinct p.type,p.model,l.speed
from laptop l
join product p on l.model=p.model
where l.speed Найдите производителей самых дешевых цветных принтеров. Вывести: maker, price

SELECT DISTINCT product.maker, printer.price
FROM product, printer
WHERE product.model = printer.model
AND printer.color = ‘y’
AND printer.price = (
SELECT MIN(price) FROM printer
WHERE printer.color = ‘y’
)

SELECT
product.maker, AVG(screen)
FROM laptop
LEFT JOIN product ON product.model = laptop.model
GROUP BY product.maker

SELECT maker, COUNT(model)
FROM product
WHERE type = ‘pc’
GROUP BY product.maker
HAVING COUNT (DISTINCT model) >= 3

SELECT product.maker, MAX(pc.price)
FROM product, pc
WHERE product.model = pc.model
GROUP BY product.maker

SELECT pc.speed, AVG(pc.price)
FROM pc
WHERE pc.speed > 600
GROUP BY pc.speed

SELECT DISTINCT maker
FROM product t1 JOIN pc t2 ON t1.model=t2.model
WHERE speed>=750 AND maker IN
( SELECT maker
FROM product t1 JOIN laptop t2 ON t1.model=t2.model
WHERE speed>=750 )

SELECT model
FROM (
SELECT model, price
FROM pc
UNION
SELECT model, price
FROM Laptop
UNION
SELECT model, price
FROM Printer
) t1
WHERE price = (
SELECT MAX(price)
FROM (
SELECT price
FROM pc
UNION
SELECT price
FROM Laptop
UNION
SELECT price
FROM Printer
) t2
)

SELECT DISTINCT maker
FROM product
WHERE model IN (
SELECT model
FROM pc
WHERE ram = (
SELECT MIN(ram)
FROM pc
)
AND speed = (
SELECT MAX(speed)
FROM pc
WHERE ram = (
SELECT MIN(ram)
FROM pc
)
)
)
AND
maker IN (
SELECT maker
FROM product
WHERE type=’printer’
)

SELECT sum(s.price)/sum(s.kol) as sredn FROM
(SELECT price,1 as kol FROM pc,product
WHERE pc.model=product.model AND product.maker=’A’
UNION all
SELECT price,1 as kol FROM laptop,product
WHERE laptop.model=product.model AND product.maker=’A’) as s

SELECT product.maker, AVG(pc.hd)
FROM pc, product WHERE product.model = pc.model
AND product.maker IN ( SELECT DISTINCT maker
FROM product
WHERE product.type = ‘printer’)
GROUP BY maker

SELECT AVG(pc.hd)
FROM pc, product
WHERE product.model = pc.model
AND product.maker IN (SELECT DISTINCT maker
FROM product WHERE product.type = ‘printer’)

SELECT t1.point, t1.date, inc, out
FROM income_o t1 LEFT JOIN outcome_o t2 ON t1.point = t2.point
AND t1.date = t2.date
UNION
SELECT t2.point, t2.date, inc, out
FROM income_o t1 RIGHT JOIN outcome_o t2 ON t1.point = t2.point
AND t1.date = t2.date

select point, date, SUM(sum_out), SUM(sum_inc)
from( select point, date, SUM(inc) as sum_inc, null as sum_out from Income Group by point, date
Union
select point, date, null as sum_inc, SUM(out) as sum_out from Outcome Group by point, date ) as t
group by point, date order by point

SELECT DISTINCT class, country
FROM classes
WHERE bore >= 16

Select country, cast(avg((power(bore,3)/2)) as numeric(6,2)) as weight
from (select country, > union all
select distinct country, > where ship=class and ship not in (select name from ships) ) a
where name IS NOT NULL group by country

SELECT o.ship FROM
BATTLES b
LEFT join outcomes o ON o.battle = b.name
WHERE b.name = ‘North Atlantic’ AND o.result = ‘sunk’

Select name from classes,ships where launched >=1922 and displacement>35000 and type=’bb’ and
ships. >

SELECT model, type
FROM product
WHERE upper(model) NOT like ‘%[^A-Z]%’
OR model not like ‘%[^0-9]%’

Select name from ships where > union
select ship as name from >

SELECT c.class
FROM classes c
LEFT JOIN (
SELECT class, name
FROM ships
UNION
SELECT ship, ship
FROM outcomes
) AS s ON s. > GROUP BY c.class
HAVING COUNT(s.name) = 1

SELECT country
FROM classes
GROUP BY country
HAVING COUNT(DISTINCT type) = 2

WITH b_s AS
(SELECT o.ship, b.name, b.date, o.result
FROM outcomes o
LEFT JOIN battles b ON o.battle = b.name )
SELECT DISTINCT a.ship FROM b_s a
WHERE UPPER(a.ship) IN
(SELECT UPPER(ship) FROM b_s b
WHERE b.date Найдите класс, имя и страну для кораблей из таблицы Ships, имеющих не менее 10 орудий.

SELECT s.class, s.name, c.country
FROM ships s
LEFT JOIN > WHERE c.numGuns >= 10

Найдите класс, имя и страну для кораблей из таблицы Ships, имеющих не менее 10 орудий.

Select Classes.class, Ships.name, Classes.country
from Ships inner join Classes
on Ships. > where Classes.numGuns > = 10

Для ПК с максимальным кодом из таблицы PC вывести все его характеристики (кроме кода) в два столбца:
— название характеристики (имя соответствующего столбца в таблице PC);
— значение характеристики

select fields,A from
(
Select
cast(model as NVARCHAR(10)) as model
, cast (speed as NVARCHAR(10)) as speed
, cast(ram as NVARCHAR(10)) as ram
,cast(hd as NVARCHAR(10)) as hd
, cast(cd as NVARCHAR(10)) as cd
, cast(price as NVARCHAR(10)) as price from PC
where code = (Select max(code) from PC)
) as t

unpivot
(
A for fields in (model, speed, ram, hd, cd, price)
) as unpvt

Илон Маск рекомендует:  scaleZ() в CSS

Найдите названия кораблей, потопленных в сражениях, и название сражения, в котором они были потоплены.

SELECT ship, battle FROM Outcomes WHERE result = ‘sunk’

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

select name
from battles
where year(date) not in
(select launched
from ships
where launched is not null)

Найдите названия всех кораблей в базе данных, начинающихся с буквы R.

select name from Ships
where name LIKE ‘R%’
UNION
SELECT Ship From Outcomes
where Ship LIKE ‘R%’

Найдите названия всех кораблей в базе данных, состоящие из трех и более слов (например, King George V).
Считать, что слова в названиях разделяются единичными пробелами, и нет концевых пробелов.

select name from ships
where name like ‘% % %’
union
select ship from outcomes
where ship like ‘% % %’

Для каждого корабля, участвовавшего в сражении при Гвадалканале (Guadalcanal), вывести название, водоизмещение и число орудий.

SELECT o.ship, displacement, numGuns FROM
(SELECT name AS ship, displacement, numGuns
FROM Ships s JOIN > UNION
SELECT class AS ship, displacement, numGuns
FROM Classes c) AS a
RIGHT JOIN Outcomes o
ON o.ship=a.ship
WHERE battle = ‘Guadalcanal’

Пронумеровать строки из таблицы Product в следующем порядке: имя производителя в порядке убывания числа производимых им моделей (при одинаковом числе моделей имя производителя в алфавитном порядке по возрастанию), номер модели (по возрастанию).
Вывод: номер в соответствии с заданным порядком, имя производителя (maker), модель (model)

SELECT count(*) OVER (order by c.countM DESC, c.maker,c.model) no, c.maker, c.model
FROM (SELECT count(*) OVER(partition by maker) countM, maker,model
FROM product) c

Найдите классы кораблей, в которых хотя бы один корабль был потоплен в сражении.

SELECT cl.class
FROM Classes cl
LEFT JOIN Ships s ON s. > WHERE cl. ) OR
s.name IN (SELECT ship FROM Outcomes WHERE result = ‘sunk’)
GROUP BY cl.class

Найдите названия кораблей с орудиями калибра 16 дюймов (учесть корабли из таблицы Outcomes).

SELECT Ships.name
FROM Classes JOIN
Ships ON > WHERE bore = 16
UNION
SELECT Outcomes.ship
FROM Outcomes JOIN
> WHERE bore = 16


Найдите сражения, в которых участвовали корабли класса Kongo из таблицы Ships.

select distinct battle from outcomes
where ship in (select name
from ships
where )

SELECT name
FROM (SELECT O.ship AS name, numGuns, displacement
FROM Outcomes O INNER JOIN
> O.ship NOT IN (SELECT name
FROM Ships
)
UNION
SELECT S.name AS name, numGuns, displacement
FROM Ships S INNER JOIN
> ) OS INNER JOIN
(SELECT MAX(numGuns) AS MaxNumGuns, displacement
FROM Outcomes O INNER JOIN
> O.ship NOT IN (SELECT name
FROM Ships
)
GROUP BY displacement
UNION
SELECT MAX(numGuns) AS MaxNumGuns, displacement
FROM Ships S INNER JOIN
> GROUP BY displacement
) GD ON OS.numGuns = GD.MaxNumGuns AND
OS.displacement = GD.displacement

SELECT DISTINCT s.name
FROM ships s
JOIN > WHERE UPPER(c.country) = ‘JAPAN’
and (numguns>=9 or numguns is NULL)
AND (c.bore Определите среднее число орудий для классов линейных кораблей.
Получить результат с точностью до 2-х десятичных знаков.

select round(avg(numguns),2)
from (
Select numguns, name
from classes left join ships using(class)
where type=’bb’ and name!=’null’ and
union all
select distinct numguns, ship
from > where ship not in (select name from ships) and )a;

SELECT c.class, t.y
FROM classes c
LEFT JOIN
(SELECT class, MIN(launched) AS y
FROM ships
GROUP BY class
) AS t ON c. >

SELECT c.class, COUNT(s.ship)
FROM classes c
LEFT JOIN
(
SELECT o.ship, sh.class
FROM outcomes o
LEFT JOIN ships sh ON sh.name = o.ship
WHERE o.result = ‘sunk’
) AS s ON s. > GROUP BY c.class

SELECT c.class, SUM(sh.sunked)
FROM classes c
LEFT JOIN (
SELECT t.name AS name, t.class AS class,
CASE WHEN o.result = ‘sunk’ THEN 1 ELSE 0 END AS sunked
FROM
(
SELECT name, class
FROM ships
UNION
SELECT ship, ship
FROM outcomes
)
AS t
LEFT JOIN outcomes o ON t.name = o.ship
) sh ON sh. > GROUP BY c.class
HAVING COUNT(DISTINCT sh.name) >= 3 AND SUM(sh.sunked) > 0

SELECT m, t,
CAST(100.0*cc/cc1 AS NUMERIC(5,2))
from
(SELECT m, t, sum(c) cc from
(SELECT distinct maker m, ‘PC’ t, 0 c from product
union all
SELECT distinct maker, ‘Laptop’, 0 from product
union all
SELECT distinct maker, ‘Printer’, 0 from product
union all
SELECT maker, type, count(*) from product
group by maker, type) as tt
group by m, t) tt1
JOIN (
SELECT maker, count(*) cc1 from product group by maker
) tt2
ON m=maker

SELECT c1, c2-
(CASE
WHEN o2 is null THEN 0
ELSE o2
END)
from
(SELECT point c1, sum(inc) c2 FROM income_o
group by point) as t1
left join
(SELECT point o1, sum(out) o2 FROM outcome_o
group by point) as t2
on c1=o1

SELECT c1, c2-
(CASE
WHEN o2 is null THEN 0
ELSE o2
END)
from
(SELECT point c1, sum(inc) c2 FROM income_o
where date Посчитать остаток денежных средств на всех пунктах приема для базы данных с отчетностью не чаще одного раза в день.

SELECT sum(i) FROM
(SELECT point, sum(inc) as i FROM
income_o
group by point

SELECT point, -sum(out) as i FROM
outcome_o
group by point
) as t

SELECT
(SELECT sum(inc) FROM Income_o WHERE date Определить имена разных пассажиров, когда-либо летевших на одном и том же месте более одного раза.

SELECT name FROM Passenger
WHERE ID_psg in
(SELECT ID_psg FROM Pass_in_trip
GROUP BY place, ID_psg
HAVING count(*)>1)

SELECT i1.point, i1.date, ‘inc’, sum(inc) FROM Income,
(SELECT point, date FROM Income
EXCEPT
SELECT Income.point, Income.date FROM Income
JOIN Outcome ON (Income.point=Outcome.point) AND
(Income.date=Outcome.date)
) AS i1
WHERE i1.point=Income.point AND i1.date=Income.date
GROUP BY i1.point, i1.date
UNION
SELECT o1.point, o1.date, ‘out’, sum(out) FROM Outcome,
(SELECT point, date FROM Outcome
EXCEPT
SELECT Income.point, Income.date FROM Income
JOIN Outcome ON (Income.point=Outcome.point) AND
(Income.date=Outcome.date)
) AS o1
WHERE o1.point=Outcome.point AND o1.date=Outcome.date
GROUP BY o1.point, o1.date

SELECT row_number() over(ORDER BY maker,s),t, type FROM
(SELECT maker,type,
CASE
WHEN type=’PC’
THEN 0
WHEN type=’Laptop’
THEN 1
ELSE 2
END AS s,
CASE
WHEN type=’Laptop’ AND (maker in (SELECT maker FROM Product WHERE
type=’PC’))
THEN

WHEN type=’Printer’ AND ((maker in (SELECT maker FROM Product WHERE
type=’PC’)) OR (maker in (SELECT maker FROM Product WHERE
type=’Laptop’)))
THEN »
ELSE maker
END AS t
FROM Product
GROUP BY maker,type) AS t1
ORDER BY maker, s

SELECT date, max(c) FROM
(SELECT date,count(*) AS c FROM Trip,
(SELECT trip_no,date FROM Pass_in_trip WHERE date>=’2003-04-01′ AND date Найти количество маршрутов, которые обслуживаются наибольшим числом рейсов.
Замечания.
1) A — B и B — A считать РАЗНЫМИ маршрутами.
2) Использовать только таблицу Trip

select count(*) from
(SELECT TOP 1 WITH TIES count(*) c, town_from, town_to from trip
group by town_from, town_to
order by c desc) as t

select count(*) from (
select TOP 1 WITH TIES sum(c) cc, c1, c2 from (
SELECT count(*) c, town_from c1, town_to c2 from trip
where town_from>=town_to
group by town_from, town_to
union all
SELECT count(*) c,town_to, town_from from trip
where town_to>town_from
group by town_from, town_to
) as t
group by c1,c2
order by cc desc
) as tt

with t as
(
select point, «date», inc, 0 AS «out» from income
union all
select point, «date», 0 AS inc, «out» from outcome
)
SELECT t.point, TO_CHAR ( t.»date», ‘DD/MM/YYYY’) AS day,
( select SUM(i.inc) from t i
where i.»date» Укажите сражения, в которых участвовало по меньшей мере три корабля одной и той же страны.

SELECT DISTINCT o.battle
FROM outcomes o
LEFT JOIN ships s ON s.name = o.ship
LEFT JOIN > WHERE c.country IS NOT NULL
GROUP BY c.country, o.battle
HAVING COUNT(o.ship) >= 3

SELECT p.maker
FROM product p
LEFT JOIN pc ON pc.model = p.model
WHERE p.type = ‘PC’
GROUP BY p.maker
HAVING COUNT(p.model) = COUNT(pc.model)

select TOP 1 WITH TIES name, c3 from passenger
join
(select c1, max(c3) c3 from
(
select pass_in_trip.ID_psg c1, Trip.ID_comp c2, count(*) c3 from pass_in_trip
join trip on trip.trip_no=pass_in_trip.trip_no
group by pass_in_trip.ID_psg, Trip.ID_comp
) as t
group by c1
having count(*)=1) as tt
on > order by c3 desc

SELECT DISTINCT c.country, b.name
FROM battles b, classes c
MINUS
SELECT c.country, o.battle
FROM outcomes o
LEFT JOIN ships s ON s.name = o.ship
LEFT JOIN > WHERE c.country IS NOT NULL
GROUP BY c.country, o.battle

SELECT c.country, c.class
FROM classes c
WHERE UPPER(c.country) = ‘RUSSIA’ AND EXISTS (
SELECT c.country, c.class
FROM classes c
WHERE UPPER(c.country) = ‘RUSSIA’ )
UNION ALL
SELECT c.country, c.class
FROM classes c
WHERE NOT EXISTS (SELECT c.country, c.class
FROM classes c
WHERE UPPER(c.country) = ‘RUSSIA’ )

select shipname,launched,batname
from
(select s.name as shipname,launched,b.name as batname,
row_number() over (partition by s.name order by «date») as num
from ships s,battles b
where to_char(«date»,’yyyy’)>=launched
and launched is not null)
where num = 1
union
(
select name,launched,(select name from battles
where «date» = (select max(«date») from battles)) as batname
from ships
where launched is null
)

Определить время, проведенное в полетах, для пассажиров, летавших всегда на разных местах. Вывод: имя пассажира, время в минутах.

WITH cte AS
(SELECT ROW_NUMBER() OVER (PARTITION BY ps.ID_psg,pit.place ORDER BY pit.date) AS rowNumber
,DATEDIFF (minute, time_out, DATEADD(DAY,IIF(time_in )
SELECT MAX(cte.name),SUM(timeFlight) FROM cte
GROUP BY cte.ID_psg
HAVING MAX(rowNumber) = 1

Определить дни, когда было выполнено максимальное число рейсов из
Ростова (‘Rostov’). Вывод: число рейсов, дата.

SELECT TOP 1 WITH TIES * FROM (
SELECT COUNT (DISTINCT P.trip_no) count, date
FROM Pass_in_trip P
JOIN Trip T ON T.trip_no = P.trip_no AND town_from = ‘Rostov’
GROUP BY P.trip_no, date) X
ORDER BY 1 DESC

Для каждого сражения определить первый и последний день
месяца,
в котором оно состоялось.
Вывод: сражение, первый день месяца, последний
день месяца.
Замечание: даты представить без времени в формате «yyyy-mm-dd».

SELECT name, REPLACE(CONVERT(CHAR(12), DATEADD(m, DATEDIFF(m,0,date),0), 102),’.’,’-‘) AS first_day,
REPLACE(CONVERT(CHAR(12), DATEADD(s,-1,DATEADD(m, DATEDIFF(m,0,date)+1,0)), 102),’.’,’-‘) AS last_day
FROM Battles

Определить пассажиров, которые больше других времени провели в полетах.
Вывод: имя пассажира, общее время в минутах, проведенное в полетах

SELECT Passenger.name, A.minutes
FROM (SELECT P.ID_psg,
SUM((DATEDIFF(minute, time_out, time_in) + 1440)%1440) AS minutes,
MAX(SUM((DATEDIFF(minute, time_out, time_in) + 1440)%1440)) OVER() AS MaxMinutes
FROM Pass_in_trip P JOIN
Trip AS T ON P.trip_no = T.trip_no
GROUP BY P.ID_psg
) AS A JOIN
Passenger ON Passenger. > WHERE A.minutes = A.MaxMinutes

Найти производителей компьютерной техники, у которых нет моделей ПК, не представленных в таблице PC.

SELECT DISTINCT maker
FROM product
WHERE maker NOT IN (
SELECT maker
FROM product
WHERE type=’PC’ AND model NOT IN (
SELECT model
FROM PC))

Из таблицы Outcome получить все записи за тот месяц (месяцы), с учетом года, в котором суммарное значение расхода (out) было максимальным.

SELECT O.*
FROM outcome O
INNER JOIN
(
SELECT TOP 1 WITH TIES YEAR(date) AS Y, MONTH(date) AS M, SUM(out) AS ALL_TOTAL
FROM outcome
GROUP BY YEAR(date), MONTH(date)
ORDER BY ALL_TOTAL DESC
) R ON YEAR(O.date) = R.Y AND MONTH(O.date) = R.M

В наборе записей из таблицы PC, отсортированном по столбцу code (по возрастанию) найти среднее значение цены для каждой шестерки подряд идущих ПК.
Вывод: значение code, которое является первым в наборе из шести строк, среднее значение цены в наборе.

WITH CTE(code,price,number)
AS
(
SELECT PC.code,PC.price, number= ROW_NUMBER() OVER (ORDER BY PC.code)
FROM PC
)
SELECT CTE.code, AVG(C.price)
FROM CTE
JOIN CTE C ON (C.number-CTE.number) =0
GROUP BY CTE.number,CTE.code
HAVING COUNT(CTE.number)=6

Определить названия всех кораблей из таблицы Ships, которые удовлетворяют, по крайней мере, комбинации любых четырёх критериев из следующего списка:
numGuns = 8
bore = 15
displacement = 32000
type = bb
launched = 1915
>
country=USA

SELECT name
FROM Ships AS s JOIN > WHERE
CASE WHEN numGuns = 8 THEN 1 ELSE 0 END +
CASE WHEN bore = 15 THEN 1 ELSE 0 END +
CASE WHEN displacement = 32000 THEN 1 ELSE 0 END +
CASE WHEN type = ‘bb’ THEN 1 ELSE 0 END +
CASE WHEN launched = 1915 THEN 1 ELSE 0 END +
CASE WHEN s. THEN 1 ELSE 0 END +
CASE WHEN country = ‘USA’ THEN 1 ELSE 0 END > = 4

Для каждой компании подсчитать количество перевезенных пассажиров (если они были в этом месяце) по декадам апреля 2003. При этом учитывать только дату вылета.
Вывод: название компании, количество пассажиров за каждую декаду

SELECT C.name, A.N_1_10, A.N_11_21, A.N_21_30
FROM (SELECT T.ID_comp,
SUM(CASE WHEN DAY(P.date) 10 AND DAY(P.date) 20 THEN 1 ELSE 0 END) AS N_21_30
FROM Trip AS T JOIN
Pass_in_trip AS P ON T.trip_no = P.trip_no AND CONVERT(char(6), P.date, 112) = ‘200304’
GROUP BY T.ID_comp
) AS A JOIN
Company AS C ON A. >

Найти производителей, которые выпускают только принтеры или только PC.
При этом искомые производители PC должны выпускать не менее 3 моделей.

select maker
from product
group by maker
having count(distinct type) = 1 and
(min(type) = ‘pc’ or
(min(type) = ‘printer’ and count(model) > 2))

Для каждого производителя перечислить в алфавитном порядке с разделителем «/» все типы выпускаемой им продукции.
Вывод: maker, список типов продукции

SELECT maker,
CASE count(distinct type) when 2 then MIN(type) + ‘/’ + MAX(type)
when 1 then MAX(type)
when 3 then ‘Laptop/PC/Printer’ END
FROM Product
GROUP BY maker

Считая, что пункт самого первого вылета пассажира является местом жительства, найти не москвичей, которые прилетали в Москву более одного раза.
Вывод: имя пассажира, количество полетов в Москву

SELECT DISTINCT name, COUNT(town_to) Qty
FROM Trip tr JOIN Pass_in_trip pit ON tr.trip_no = pit.trip_no JOIN
Passenger psg ON pit. > WHERE town_to = ‘Moscow’ AND pit.ID_psg NOT IN(SELECT DISTINCT ID_psg
FROM Trip tr JOIN Pass_in_trip pit ON tr.trip_no = pit.trip_no
WHERE date+time_out = (SELECT MIN (date+time_out)
FROM Trip tr1 JOIN Pass_in_trip pit1 ON tr1.trip_no = pit1.trip_no
WHERE pit. > AND town_from = ‘Moscow’)
GROUP BY pit.ID_psg, name
HAVING COUNT(town_to) > 1

Среди тех, кто пользуется услугами только одной компании, определить имена разных пассажиров, летавших чаще других.
Вывести: имя пассажира, число полетов и название компании.

SELECT
(SELECT name FROM Passenger WHERE > B.trip_Qty,
(SELECT name FROM Company WHERE > FROM (SELECT P.ID_psg, MIN(T.ID_comp) AS ID_comp, COUNT(*) AS trip_Qty, MAX(COUNT(*)) OVER() AS Max_Qty
FROM Pass_in_trip AS P JOIN
Trip AS T ON P.trip_no = T.trip_no
GROUP BY P.ID_psg
HAVING MIN(T. > ) AS B
WHERE B.trip_Qty = B.Max_Qty

Найти производителей, у которых больше всего моделей в таблице Product, а также тех, у которых меньше всего моделей.
Вывод: maker, число моделей

select Maker , count(distinct model) Qty from Product
group by maker
having count(distinct model) > = ALL
(select count(distinct model) from Product
group by maker)
or
count(distinct model) Вывести все строки из таблицы Product, кроме трех строк с наименьшими номерами моделей и трех строк с наибольшими номерами моделей.

Select maker, model, type from
(
Select
row_number() over (order by model) p1,
row_number() over (order by model DESC) p2,

  • from Product

) t1
where p1 > 3 and p2 > 3

Используя таблицу Product, определить количество производителей, выпускающих по одной модели.

select count(maker)
from product
where maker in
(
Select maker from product
group by maker
having count(model) = 1
)

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

SELECT Q_NAME
FROM utQ
WHERE Q_ID IN (SELECT DISTINCT B.B_Q_ID
FROM (SELECT B_Q_ID
FROM utB
GROUP BY B_Q_ID
HAVING SUM(B_VOL) = 765) AS B
WHERE B.B_Q_ID NOT IN (SELECT B_Q_ID
FROM utB
WHERE B_V_ID IN (SELECT B_V_ID
FROM utB
GROUP BY B_V_ID
HAVING SUM(B_VOL) Для каждой компании, перевозившей пассажиров, подсчитать время, которое провели в полете самолеты с пассажирами.
Вывод: название компании, время в минутах.

select c.name, sum(vr.vr)
from
(select distinct t.id_comp, pt.trip_no, pt.date,t.time_out,t.time_in,—pt.id_psg,
case
when DATEDIFF(mi, t.time_out,t.time_in)> 0 then DATEDIFF(mi, t.time_out,t.time_in)
when DATEDIFF(mi, t.time_out,t.time_in) group by c.name

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

SELECT DATEADD(day, S.Num, D.date) AS Dt,
(SELECT COUNT(DISTINCT P.trip_no)
FROM Pass_in_trip P
JOIN Trip T
ON P.trip_no = T.trip_no
AND T.town_from = ‘Rostov’
AND P.date = DATEADD(day, S.Num, D.date)) AS Qty
FROM (SELECT (3 * ( x — 1 ) + y — 1) AS Num
FROM (SELECT 1 AS x UNION ALL SELECT 2 UNION ALL SELECT 3) AS N1
CROSS JOIN (SELECT 1 AS y UNION ALL SELECT 2 UNION ALL SELECT 3) AS N2
WHERE (3 * ( x — 1 ) + y ) На основании информации из таблицы Pass_in_Trip, для каждой авиакомпании определить:
1) количество выполненных перелетов;
2) число использованных типов самолетов;
3) количество перевезенных различных пассажиров;
4) общее число перевезенных компанией пассажиров.
Вывод: Название компании, 1), 2), 3), 4).

SELECT name,
COUNT(DISTINCT CONVERT(CHAR(24),date)+CONVERT(CHAR(4),Trip.trip_no)),
COUNT(DISTINCT plane),
COUNT(DISTINCT ID_psg),
COUNT(*)
FROM Company,Pass_in_trip,Trip
WHERE Company. > GROUP BY Company.ID_comp,name

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

with r as (select v.v_name,
v.v_id,
count(case when v_color = ‘R’ then 1 end) over(partition by v_id) cnt_r,
count(case when v_color = ‘B’ then 1 end) over(partition by b_q_id) cnt_b
from utV v join utB b on v.v_ > select v_name
from r
where cnt_r > 1
and cnt_b > 0
group by v_name

Отобрать из таблицы Laptop те строки, для которых выполняется следующее условие:
значения из столбцов speed, ram, price, screen возможно расположить таким образом, что каждое последующее значение будет превосходить предыдущее в 2 раза или более.
Замечание: все известные характеристики ноутбуков больше нуля.
Вывод: code, speed, ram, price, screen.

select code, speed, ram, price, screen
from laptop where exists (
select 1 x
from (
select v, rank()over(order by v) rn
from ( select cast(speed as float) sp, cast(ram as float) rm,
cast(price as float) pr, cast(screen as float) sc
)l unpivot(v for c in (sp, rm, pr, sc))u
)l pivot(max(v) for rn in ([1],[2],[3],[4]))p
where [1]*2 Вывести список ПК, для каждого из которых результат побитовой операции ИЛИ, примененной к двоичным представлениям скорости процессора и объема памяти, содержит последовательность из не менее четырех идущих подряд единичных битов.
Вывод: код модели, скорость процессора, объем памяти.

with CTE AS
(select
1 n, cast (0 as varchar(16)) bit_or,
code, speed, ram FROM PC
UNION ALL
select n*2,
cast (convert(bit,(speed|ram)&n) as varchar(1))+cast(bit_or as varchar(15))
, code, speed, ram
from CTE where n 0

Рассматриваются только таблицы Income_o и Outcome_o. Известно, что прихода/расхода денег в воскресенье не бывает.
Для каждой даты прихода денег на каждом из пунктов определить дату инкассации по следующим правилам:
1. Дата инкассации совпадает с датой прихода, если в таблице Outcome_o нет записи о выдаче денег в эту дату на этом пункте.
2. В противном случае — первая возможная дата после даты прихода денег, которая не является воскресеньем и в Outcome_o не отмечена выдача денег сдатчикам вторсырья в эту дату на этом пункте.
Вывод: пункт, дата прихода денег, дата инкассации.

select point,
«date» income_date,
«date» + nvl(
min(case when diff > cnt then cnt else null end),
max(cnt)+1
) incass_date
from (select i.point,
i.»date»,
(trunc(o.»date») — trunc(i.»date»)) diff, — разница дней
— количество запрещенных для инкассации дней после прихода и до текущего запрещенного дня
count(1) over (partition by i.point, i.»date» order by o.»date» rows between unbounded preceding and current row)-1 cnt
from income_o i
join (select point, «date», 1 disabled from outcome_o
union
select point, trunc(«date»+7,’DAY’), 1 disabled from income_o) o
on i.point = o.point
where o.»date» > = i.»date»)
group by point, «date»

Написать запрос, который выводит все операции прихода и расхода из таблиц Income и Outcome в следующем виде:
дата, порядковый номер записи за эту дату, пункт прихода, сумма прихода, пункт расхода, сумма расхода.
При этом все операции прихода по всем пунктам, совершённые в течение одного дня, упорядочены по полю code, и так же все операции расхода упорядочены по полю code.
В случае, если операций прихода/расхода за один день было не равное количество, выводить NULL в соответствующих колонках на месте недостающих операций.

Select distinct A.date , A.R, B.point, B.inc, C.point, C.out
From (Select distinct date, ROW_Number() OVER(PARTITION BY date ORDER BY code asc) as R From Income
Union Select distinct date, ROW_Number() OVER(PARTITION BY date ORDER BY code asc) From Outcome) A
LEFT Join (Select date, point, inc
, ROW_Number() OVER(PARTITION BY date ORDER BY code asc) as RI FROM Income
) B on B.date=A.date and B.RI=A.R
LEFT Join (Select date, point, out
, ROW_Number() OVER(PARTITION BY date ORDER BY code asc) as RO FROM Outcome
) C on C.date=A.date and C.RO=A.R

Таблица Printer сортируется по возрастанию поля code.
Упорядоченные строки составляют группы: первая группа начинается с первой строки, каждая строка со значением color=’n’ начинает новую группу, группы строк не перекрываются.
Для каждой группы определить: наибольшее значение поля model (max_model), количество уникальных типов принтеров (distinct_types_cou) и среднюю цену (avg_price).
Для всех строк таблицы вывести: code, model, color, type, price, max_model, distinct_types_cou, avg_price.

SELECT code, model, color, type, price,
MAX(model)OVER(PARTITION BY Grp)max_model,
MAX(CASE type WHEN’Laser’THEN 1 ELSE 0 END)OVER(PARTITION BY Grp)+
MAX(CASE type WHEN’Matrix’THEN 1 ELSE 0 END)OVER(PARTITION BY Grp)+
MAX(CASE type WHEN’Jet’THEN 1 ELSE 0 END)OVER(PARTITION BY Grp)distinct_types,
AVG(price)OVER(PARTITION BY Grp)
FROM(
SELECT *,
CASE color WHEN’n’THEN 0 ELSE ROW_NUMBER()OVER(ORDER BY code)END+
CASE color WHEN’n’THEN 1 ELSE-1 END*ROW_NUMBER()OVER(PARTITION BY color ORDER BY code)Grp
FROM Printer
)T

Определить имена разных пассажиров, которые летали
только между двумя городами (туда и/или обратно).

select name from passenger
where id_psg in
(
select id_psg from trip t,pass_in_trip pit
where t.trip_no=pit.trip_no
group by id_psg
having count(distinct case when town_from Выбрать три наименьших и три наибольших номера рейса. Вывести их в шести столбцах одной строки, расположив в порядке от наименьшего к наибольшему.
Замечание: считать, что таблица Trip содержит не менее шести строк.

Select min(t.trip_no),min(tt.trip_no),min(ttt.trip_no),max(t.trip_no),max(tt.trip_no),max(ttt.trip_no)
from trip t, trip tt, trip ttt
where tt.trip_no > t.trip_no and ttt.trip_no > tt.trip_no

Для каждого класса крейсеров, число орудий которого известно, пронумеровать (последовательно от единицы) все орудия.
Вывод: имя класса, номер орудия в формате ‘bc-N’.

with a as(
select x.class,x.numGuns,row_number()over(partition by x.class order by x.numguns)n
from Classes x,classes y
where x.type=’bc’)
select distinct class,’bc-‘+cast(n as char(2))
from a where numguns> =n

Статистики Алиса, Белла, Вика и Галина нумеруют строки у таблицы Product.
Все четверо упорядочили строки таблицы по возрастанию названий производителей.
Алиса присваивает новый номер каждой строке, строки одного производителя она упорядочивает по номеру модели.
Трое остальных присваивают один и тот же номер всем строкам одного производителя.
Белла присваивает номера начиная с единицы, каждый следующий производитель увеличивает номер на 1.
У Вики каждый следующий производитель получает такой же номер, какой получила бы первая модель этого производителя у Алисы.
Галина присваивает каждому следующему производителю тот же номер, который получила бы его последняя модель у Алисы.
Вывести: maker, model, номера строк получившиеся у Алисы, Беллы, Вики и Галины соответственно.

select maker, model,
row_number() over (order by maker, model),
dense_rank() over (order by maker),
rank() over (order by maker),
count(*) over (order by maker)
from product

Пусть v1, v2, v3, v4, . представляет последовательность вещественных чисел — объемов окрасок b_vol, упорядоченных по возрастанию b_datetime, b_q_id, b_v_id.
Найти преобразованную последовательность P1=v1, P2=v1/v2, P3=v1/v2*v3, P4=v1/v2*v3/v4, . где каждый следующий член получается из предыдущего умножением на vi (при нечетных i) или делением на vi (при четных i).
Результаты представить в виде b_datetime, b_q_id, b_v_id, b_vol, Pi, где Pi — член последовательности, соответствующий номеру записи i. Вывести Pi с 8-ю знаками после запятой.

with a as(
select *,row_number()over(order by b_datetime,b_q_id,b_v_id) n from utb)
select b_datetime,b_q_id,b_v_id,b_vol,
cast(exp(sm1)/exp(sm2) as numeric(12,8))k
from a x
cross apply
(select sum( iif(n%2<> 0,log(b_vol),0)) sm1,sum( iif(n%2=0,log(b_vol),0)) sm2 from a where n Для пятого по счету пассажира из числа вылетевших из Ростова в апреле 2003 года определить компанию, номер рейса и дату вылета.
Замечание. Считать, что два рейса одновременно вылететь из Ростова не могут.

Select name, trip_no, date
from(
select row_number() over(order by date+time_out,ID_psg) rn,name,Trip.trip_no,date
from Company,Pass_in_trip,Trip
where Company. > and town_from=’Rostov’ and year(date)=2003 and month(date)=4)_
where rn=5

Реставрация экспонатов секции «Треугольники» музея ПФАН проводилась согласно техническому заданию. Для каждой записи таблицы utb малярами подкрашивалась сторона любой фигуры, если длина этой стороны равнялась b_vol.
Найти окрашенные со всех сторон треугольники, кроме равносторонних, равнобедренных и тупоугольных.
Для каждого треугольника (но без повторений) вывести три значения X, Y, Z, где X — меньшая, Y — средняя, а Z — большая сторона.

SELECT DISTINCT b1.B_VOL, b2.b_vol, b3.b_vol FROM utb b1, utb b2, utb b3
WHERE b1.B_VOL SQRT( SQUARE(b1.B_VOL) + SQUARE(b2.B_VOL)))

Вывести:
1. Названия всех квадратов черного или белого цвета.
2. Общее количество белых квадратов.
3. Общее количество черных квадратов.

SELECT A.Q_NAME AS q_name,
A.Whites AS Whites,
A.Cnt — A.Whites AS Blacks
FROM (SELECT Q.Q_ID,
Q.Q_NAME,
(SUM(SUM(B.B_VOL)) OVER())/765 AS Whites,
COUNT(*) OVER() AS Cnt
FROM utQ AS Q
LEFT JOIN utB AS B
ON Q.Q_ > GROUP BY Q.Q_ID,
Q.Q_NAME
HAVING SUM(B.B_VOL) = 765
OR SUM(B.B_VOL) IS NULL) AS A

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

select name from passenger where id_psg in
(select id_psg
from pass_in_trip pit join trip t on pit.trip_no = t.trip_no
where time_in Найти НЕ белые и НЕ черные квадраты, которые окрашены разными цветами в пропорции 1:1:1. Вывод: имя квадрата, количество краски одного цвета

select B_Q_ID, sum(vol)/3 vol
from
(select B_Q_ID, V_COLOR, sum(B_VOL) vol
from utB, utV
where B_V_ > group by B_Q_ID, V_COLOR
) z
group by B_Q_ID
having count(v_color)=3
and sum(vol) Какое максимальное количество черных квадратов можно было бы окрасить в белый цвет
оставшейся краской

select min(Qty) from (select SUM(RemainPaint)/255 Qty FROM (select V_COLOR, V_ID,
CASE
WHEN SUM(B_VOL) IS NULL
THEN 255
ELSE 255-SUM(B_VOL)
END RemainPaint
from utB right join utV on B_V_ > group by V_COLOR, V_ID
) R
group by V_COLOR
) Q

Сколько каждой краски понадобится, чтобы докрасить все Не белые квадраты до белого цвета.
Вывод: количество каждой краски в порядке (R,G,B)

SELECT sum(255-ISNULL ([R],0) ) R , sum(255-isnull([G],0)) G, sum(255-isnull([B],0)) B
FROM
(
/*merging all tables to find paint filling and color for all squares*/
select ISNULL(B_Q_ID, Q_ID) ID, V_COLOR, B_VOL Vol from
utB RIGHT JOIN utQ on B_Q_ > LEFT JOIN utV on B_V_ > ) as SourceT
PIVOT
(
/*rotating table and calculating each paint volume for each square*/
SUM(Vol) For V_COLOR IN ([R], [G], [B])
) Pvt
/*excluding white squares*/
where ISNULL ([R],0) + isnull([G],0) + isnull([B],0) Определить имена разных пассажиров, которым чаще других доводилось лететь на одном и том же месте. Вывод: имя и количество полетов на одном и том же месте.

WITH b AS
(SELECT ID_psg, COUNT(*) as cnt FROM Pass_In_Trip GROUP BY ID_psg, place),
b1 AS
(SELECT DISTINCT > SELECT name, cnt FROM b1 JOIN Passenger p ON (b1. >

Рассмотрим равнобочные трапеции, в каждую из которых можно вписать касающуюся всех сторон окружность. Кроме того, каждая сторона имеет целочисленную длину из множества значений b_vol.
Вывести результат в 4 колонки: Up, Down, Side, Rad. Здесь Up — меньшее основание, Down — большее основание, Side — длины боковых сторон, Rad – радиус вписанной окружности (с 2-мя знаками после запятой).

select distinct Up=u.b_vol, Down=d.b_vol, S > Rad=cast(POWER((POWER(s.b_vol,2)-POWER((1.*d.b_vol-1.*u.b_vol)/2,2)),1./2.)/2 as dec(15,2))
from utB u, utB d, utB s
where u.b_vol Считая, что каждая окраска длится ровно секунду, определить непрерывные интервалы времени с длительностью более 1 секунды из таблицы utB.
Вывод: дата первой окраски в интервале, дата последней окраски в интервале.

SELECT MIN(D)start, MAX(D)finish
FROM
(
SELECT D, SUM(F)OVER(ORDER BY D ROWS UNBOUNDED PRECEDING)F
FROM
(
SELECT B_DATETIME D, IIF(IsNull(DATEDIFF(second, LAG(B_DATETIME)OVER(ORDER BY B_DATETIME), B_DATETIME),0) 0

По таблице Classes для каждой страны найти максимальное значение среди трех выражений:
numguns*5000, bore*3000, displacement.
Вывод в три столбца:
— страна;
— максимальное значение;
— слово `numguns` — если максимум достигается для numguns*5000, слово `bore` — если максимум достигается для bore*3000, слово `displacement` — если максимум достигается для displacement.
Замечание. Если максимум достигается для нескольких выражений, выводить каждое из них отдельной строкой.

Select top 1 with ties country, x, n
from classes
cross apply(values(numguns*5000,’numguns’)
,(bore*3000,’bore’)
,(displacement,’displacement’))V(x,n)
group by country, x, n
order by rank()over(partition by country order by x desc)

Выборы Директора музея ПФАН проводятся только в високосный год, в первый вторник апреля после первого понедельника апреля.
Для каждой даты из таблицы Battles определить дату ближайших (после этой даты) выборов Директора музея ПФАН.
Вывод: сражение, дата сражения, дата выборов. Даты выводить в формате «yyyy-mm-dd».

Select name, convert(char(10),date,120) as battle_dt
,convert(char(10),MIN(Dateadd(dd,1,dt)),120) as election_dt
From
(Select name, date, Dateadd(yy,p,Dateadd(dd,n,Dateadd(mm,3,dateadd(yy,datediff(yy,0,date),0)))) as dt
From Battles
,(values(0),(1),(2),(3),(4),(5),(6),(7),(8)) T(p)
,(values(0),(1),(2),(3),(4),(5),(6)) W(n) ) X
Where date 0 or Year(dt)%400=0)
and DATEPART(dw,dt)=DATEPART(dw,’20140106′)
GROUP BY name, date

Сгруппировать все окраски по дням, месяцам и годам. Идентификатор каждой группы должен иметь вид «yyyy» для года, «yyyy-mm» для месяца и «yyyy-mm-dd» для дня.
Вывести только те группы, в которых количество различных моментов времени (b_datetime), когда выполнялась окраска, более 10.
Вывод: идентификатор группы, суммарное количество потраченной краски.

select to_char(trunc(b.b_datetime,’year’),’yyyy’) grp, sum(b.b_vol) qnt
from utB b
group by to_char(trunc(b.b_datetime,’year’),’yyyy’)
having count(distinct b.b_datetime) > 10
union
select to_char(trunc(b.b_datetime,’MM’),’yyyy-mm’) grp, sum(b.b_vol) qnt
from utB b
group by to_char(trunc(b.b_datetime,’MM’),’yyyy-mm’)
having count(distinct b.b_datetime) > 10
union
select to_char(trunc(b.b_datetime,’dd’),’yyyy-mm-dd’) grp, sum(b.b_vol) qnt
from utB b
group by to_char(trunc(b.b_datetime,’dd’),’yyyy-mm-dd’)
having count(distinct b.b_datetime) > 10

Для авиакомпаний, самолеты которой выполнили хотя бы один рейс, вычислить с точностью до двух десятичных знаков средние величины времени нахождения самолетов в воздухе (в минутах). Также рассчитать указанные характеристики по всем летавшим самолетам (использовать слово ‘TOTAL’).
Вывод: компания, среднее арифметическое, среднее геометрическое, среднее квадратичное, среднее гармоническое.

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL