Содержание

6 SQL-запросов, о которых должен знать каждый дата-инженер | by Андрей Шагин | NOP::Nuances of Programming

Знание продвинутого синтаксиса SQL необходимо и новичку, и опытному дата-инженеру или аналитику данных.

В связи с бурным ростом объема данных все более важным становится умение очень быстро их анализировать.

Источник: Statista

Объем данных на этом графике показан в зеттабайтах.

1 зеттабайт = 1 триллион гигабайтов

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

Высококачественными и очень надежными для относительно естественного моделирования данных их делают ACID-свойства SQL.

Я и сам дата-инженер, давно использую SQL и знаю, как важно быстрее писать сложные запросы. И продвинутый синтаксис SQL будет здесь очень кстати.

В примерах использованы данные таблицы bill («Счет»):

Изображение автора

Нарастающий итог

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

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

Вот запрос на эту сумму:

SELECT id,month
, Amount
, SUM(Amount) OVER (ORDER BY id) as total_sum
FROM bill

А вот как будет выглядеть результат:

Изображение автора

Обобщенные табличные выражения

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

Фактически это временный именованный результирующий набор данных, на который можно ссылаться внутри оператора SELECT, INSERT, UPDATE или DELETE.

Рассмотрим простой запрос:

SELECT *
FROM bill
WHERE id in
(SELECT DISTINCT id
FROM id
WHERE country = "US"
AND status = "Y"
)

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

WITH idtempp as (
SELECT id as id
FROM id
WHERE country = "US"
AND status = "Y"
)

SELECT *
FROM bill
WHERE id in (SELECT id from idtempp)

Упорядочение данных

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

SELECT 
id,
Amount,
RANK() OVER (ORDER BY Amount desc)
FROM bill

В этом запросе набор данных упорядочен по столбце amount («Сумма»).

Вместо RANK() используется также DENSE_RANK(). Он аналогичен, но не пропускает следующее по порядку значение, если у двух строк одинаковое значение.

Добавление подытогов

Наличие промежуточного итога (подытога) помогает оценить данные в контексте общего итога.

Это расширенная версия оператора GROUP BY: здесь есть возможность добавления к данным промежуточных и общих итогов.

SELECT  
Type,
id,
SUM (Amount) AS total_amount
FROM bill
GROUP BY Type,id WITH ROLLUP
Изображение автора

Примечание: это запрос в MySQL. Для других синтаксис свертки может отличаться.

Здесь в запросе строка со значениями null и для типа, и для идентификатора — это итог. Есть также подытоги со значениями null только в столбце идентификатора: это 4-я и предпоследняя строки.

Временные функции

Временные функции позволяют легко менять данные без использования огромных операторов case.

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

CREATE TEMPORARY FUNCTION get_gender(type varchar) AS (
CASE WHEN type = "M" THEN "male"
WHEN type = "F" THEN "female"
ELSE "n/a"
END
)
SELECT
name,
get_gender(Type) as gender
FROM bill

Дисперсия и среднеквадратическое отклонение

Для получения этих значений есть специальные агрегатные функции: VARIANCE, VAR_POP и VAR_SAMP. Они группируют данные и используются для определения дисперсии, дисперсии группы и дисперсии выборки набора данных по отдельности.

SELECT 
VARIANCE(amount) AS var_amount,
VAR_POP(amount) AS var_pop_amount,
VAR_SAMP(amount) AS var_samp_amount,
STDDEV_SAMP(amount) as stddev_sample_amount,
STDDEV_POP(amount) as stddev_pop_amount,
FROM bill

VAR_POP — дисперсия совокупности;
VAR_SAMP — дисперсия выборки;
STDDEV_SAMP — среднеквадратическое отклонение для выборки;
STDDEV_POP — среднеквадратическое отклонение для совокупности.

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

Stats подтверждает, что экосистема инструментов SQL, которая включает в себя все: от Excel и Tableau до SparkSQL — используется в более чем 60 % организаций. Это настоящий подвиг для SQL, особенно учитывая его возраст.

Уверен, что и вам как дата-инженеру эти команды будут полезны.

Читайте также:

  • Как подключить базу данных MySQL к сайту на PHP
  • SQL в науке о данных
  • Руководство по анализу данных с SQL

Читайте нас в Telegram, VK и Яндекс.Дзен

Перевод статьи Cinto: 6 SQL Queries Every Data Engineer Should Be Aware of

Сложные запросы. Microsoft Access 2007

Сложные запросы

С помощью сложных запросов можно выполнить следующее.

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

• Выбрать данные по заданному пользователем условию.

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

• Отобрать некоторые записи из таблиц с помощью какого-либо условия.

Запросы с вычисляемыми полями

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

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

Теперь создайте запрос с вычисляемым полем.

1. Откройте желаемую базу данных Microsoft Access 2007 ( Отдел продаж ).

2. Перейдя на вкладку Создание в группе Другие, нажмите кнопку Конструктор запросов . Будет создан новый запрос, и на экране вы увидите окно

Добавление таблицы (см. рис. 5.7).

3. Перейдите на вкладку Таблицы и выберите нужную таблицу (например, Клиенты ). Затем нажмите кнопку Добавить , а после этого – кнопку Закрыть . Пустой бланк запроса отобразится на экране.

4. Чтобы создать вычисляемое поле с названием Данные , нажмите на ячейке Поле в столбце бланка запроса и введите следующее: Данные: [Телефон]+” “+[Адрес].

5. Если вы установите флажок Вывод на экран

в столбце бланка запроса, то в результате отобразится данное поле запроса.

6. Вы также можете установить сортировку, щелкнув кнопкой мыши на параметре Сортировка в столбце бланка запроса и выбрав вариант По возрастанию в раскрывающемся списке. Измененный бланк запроса будет таким, как показано на рис. 5.17.

Рис. 5.17. Готовый бланк запроса

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

8. В поле

Имя запроса вы можете ввести название нового запроса. Затем нажмите кнопку ОК .

9. Перейдите на вкладку Конструктор , а затем нажмите кнопку Выполнить . После этого вы можете увидеть результат измененного запроса (рис. 5.18).

Рис. 5.18. Результат измененного запроса

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

Внутреннее соединение таблиц

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

• Внутреннее соединение – соединение также называют эквисоединением – один из самых распространенных типов соединения, которое может связывать записи в таблицах базы данных отношением равенства.

Access 2007 может автоматически создавать эквисоединения при наличии двух условий:

– если в таблице есть поля с идентичными именами, а также согласованными типами, причем хотя бы одно из этих полей должно быть ключевым;

– данное соединение было задано пользователем в окне Схема данных .

• Внешнее соединение – соединение, использующееся для создания запроса, который объединяет все записи из одной таблицы и записи из другой таблицы (но только те, в которых связанные поля совпадают).

• Соединение по отношению – тета-соединение необходимо использовать в том случае, если вы хотите связать данные любым отношением. Причем такое соединение не выводится в окне Конструктора и в окне Схемы данных .

• Рекурсивное соединение – еще один вид соединения для совмещения данных в одной таблице. Создается при добавлении в запрос копии таблицы, поля похожих таблиц связываются.

В Microsoft Access 2007 используются некоторые слова языка SQL:

• INNER JOIN – для указаний внутренних соединений;

• LEFT JOIN или RIGHT JOIN – для указания внешних соединений;

• WHERE поле1=поле2 – внутреннее соединение;

• WHERE поле1>поле2 – соединение по отношению.

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

1. Откройте желаемую базу данных Microsoft Access 2007 ( Отдел продаж ).

2. Перейдя на вкладку Создания в группе Другие , нажмите кнопку Конструктор запросов . Будет создан новый запрос, и на экране вы увидите окно Добавление таблицы (см. рис. 5.7).

3. Перейдите на вкладку Таблицы и выберите нужную (например, Клиенты ), нажмите кнопку

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

Рис. 5.19. Пустой бланк запроса, сверху видны структуры таблиц и их связь

4. Выберите необходимые поля из двух макетов таблиц двойным щелчком кнопки мыши на названии поля (например, Имя , Телефон , Адрес , Товар , Количество

).

5. Если вы установите флажок Вывод на экран в столбце бланка запроса, отобразится данное поле запроса.

6. Вы также можете установить сортировку, для этого щелкните кнопкой мыши на параметре Сортировка в столбце бланка запроса нужного вам поля. В открывающемся списке выберите нужный вариант сортировки (рис. 5.20).

Рис. 5.20. Настроенный бланк запроса

В листинге 5.2 приведен SQL-текст вашего запроса.

Данный текст является ознакомительным фрагментом.

4.2.1 Сложные командные строки

4.2.1 Сложные командные строки Каждая командная строка выполняется в своей собственной подоболочке, таким образом, команды cd в командной строке влияют только на строку, в которой они записаны. Любую строку в make-файле можно расширить на множество строк, указывая в конце

6.6. Сложные переходы

6.6. Сложные переходы Рассмотренное выше понятие перехода является вполне достаточным для большинства типичных расчетно-вычислительных задач. Однако современные программные системы могут реализовывать очень сложную логику поведения отдельных своих компонентов. Может

Сложные запросы: выручат скобки

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

Сложные выражения JavaScript

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

Сложные выражения выполняются специальным образом и служат для особых целей — в основном, для управления процессом выполнения

Как рисуются сложные контуры

Как рисуются сложные контуры Контуры сложных фигур рисуются в три этапа.1. Web-обозреватель ставится в известность, что сейчас начнется рисование контура сложной фигуры.2. Рисуются отдельные линии, прямые и кривые, составляющие сложный контур.3. Web-обозреватель ставится в

Сложные объемные тела

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

11.1.3. Более сложные конструкторы

11. 1.3. Более сложные конструкторы По мере усложнения объектов у них появляется все больше атрибутов, которые необходимо инициализировать в момент создания. Соответствующий конструктор может оказаться длинным и запутанным, его параметры даже не будут помещаться на одной

11.2. Более сложные механизмы

11.2. Более сложные механизмы Не все в модели ООП, реализованной в Ruby, одинаково очевидно. Что-то сложнее, что-то применяется реже. Линия раздела для каждого программиста проходит в разных местах. В этой части главы мы попытались собрать те средства, которые не так просты или

Сложные объемные тела

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

Сложные команды.

Сложные команды. Для дешифровки сообщения, оставляя подпись на нем нетронутой:pgp –d ciphertextfileДля создания удостоверяющей подписи отдельно от документа:pgp –sb textfile [-u your_userid]Для отделения удостоверяющей подписи от подписанного сообщения:pgp –b

Глава 17 Сложные приемы

Глава 17 Сложные приемы • Выполнение и оптимизация• Экран загрузки• Защита от копирования• Список лучших игроков• Определение версии Flash-плагинаХотя в предыдущих главах речь шла о сотнях алгоритмов ActionScript, многое осталось «за кадром». Мы не стали для иллюстрации этих

Сложные проблемы

Сложные проблемы Сборщик мусора сталкивается со следующими проблемами, вызванными практическими ограничениями на размещение объектов в современной ОО-среде:[x]. ОО-подпрограммы могут вызывать внешние программы, в частности, С-функции, которые могут, в свою очередь,

Более сложные трансформации

Более сложные трансформации От простого — к сложному. Это вечный путь познания. Последуем им и мы.Сложные трансформации графики (вращение, сдвиг, изменение размеров и пр.) выполняются во Flash 8 с помощью особого инструмента, называемого Free Transform (Трансформатор). Чтобы

Более сложные эффекты

Более сложные эффекты Закончив с эффектами простейшими, перейдем к более сложным и более, если так можно сказать, эффектным. Их побольше — целых

Сложные выражения ActionScript

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

Демистификация сложных запросов для Django ORM | Статьи о Django

Мотивация

Итак, я работал над созданием своего личного проекта, когда я натолкнулся на препятствие при написании определенного запроса. Я хорошо разбираюсь в SQL как таковом, но я почувствовал себя растерянным, когда попытался преобразовать эту логику в классическое объектно-реляционное сопоставление (ORM) Django. Это заставило меня пройти через несколько болезненных часов, пока один джентльмен наконец не ответил на мой конкретный вопрос о переполнении стека. После этого ответа я решил просмотреть несколько ресурсов и аккуратную документацию Django, чтобы составить небольшое руководство по созданию вашей сложной логики SQL в рамках предоставленной ORM.

Вступление

Эта статья предполагает базовые знания Django и основы SQL. Основные темы, которые я стремлюсь охватить: агрегирование, функции, подзапросы, оконные функции. Я стремлюсь добавить больше концепций, поскольку чувствую личную потребность в их использовании. Эмпирическое правило: любое выражение, которое является более сложным или требует больше времени, чем ваша доступная пропускная способность? Просто напишите необработанный SQL в курсор Django. Это не лучший метод, так как это довольно уязвимые SQL-инъекции. Тем не менее, при соблюдении надлежащих правил и функционального программирования атаки с использованием инъекций также могут быть защищены.

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

Агрегирование

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

Aggregate()

Предположим, у вас есть модель вопроса, в которой каждый вопрос поддерживает поле ManyToMany с пользователем, обозначающее отношения «Follower». Если мне нужна сводка голосов, полученных за вопрос, я могу выполнить следующий запрос:


>>> from django.db.models import Count
>>> Question. objects.aggregate(
        avg_followers = Avg(Count('followers')),
        highest_followers = Max(Count('followers'))
        lowest_followers = Min(Count('followers'))
    ){'avg_followers' : 14.23, 'highest_followers' : 1523, 'lowest_followers' : 0}

Обратите внимание, как мне пришлось импортировать функцию Count и заключить в нее поле «followers». Followers — это ManyToManyField, функция Count возвращает количество пользователей, которые подписались на вопрос. На основе этого результата по полному набору запросов находятся соответствующие минимальные, максимальные и средние подписчики.

Annotate()

Как вкратце объяснено выше, аннотация используется для создания индивидуальной сводки для каждого объекта в наборе запросов. Это означает, что результат агрегирования вычисляется для каждой отдельной записи, которая может быть или не совпадать. Если бы я хотел создать счетчик «за» для всех проголосовавших за ответ в модели ответа:


>>> from django.db.models import Count
>>> query = Answers.objects.annotate(upvotes = Count('upvoters'))
>>> query[0]
<Answer : 1>
>>> query[0].upvotes
143
>>> query[1]
<Answer : 2>
>>> query[1].upvotes
23

F() выражения

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


>>> from django.db.models import F
>>> query = Answer.objects.get(author__username='keshavvinayak01')
>>> query.answer
Yes, Math is in fact related to Science.
>>> query. update(answer = F('answer') + " [Anonymous]")
>>> query.answer
Yes, Math is in fact related to Science. [Anonymous]

Мы можем использовать эти выражения в аннотациях, фильтрах или ссылках на внешний ключ.


>>> from django.db.models import F
# В аннотациях
>>> answer = Answer.objects.annotate(
        interest = Count(F('followers') + Count(F('requested')
    )
# В фильтрах
>>> own_qa = Answer.objects.filter(
        question__asker = F('author')
    )
# Ссылка на внешний ключ
>>> answer = Answer.objects.annotate(
        question_id = F('question')
    )
>>> answer.question
Is Math related to Science?
>>> answer.question_id
3

Func() выражения

Эти выражения включают функции базы данных, такие как LOWER или COALESCE. Вот несколько примеров:


LOWER
>>> from django. db.models import F, Func, Coalesce
>>> quest = Question.objects.annotate(
        lower_question = Func(F('question')),
        function = 'LOWER'
    )
# Все тексты вопросов будут в нижнем регистре.

COALESCE
>>> from datetime import datetime
>>> q = Answer.objects.annotate(
            updated_at = Coalesce(F('updated_at'), datetime.now())
        )

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

Subquery() выражения

Мы можем добавить явный подзапрос в наш набор запросов, используя выражения Subquery(). Например, если мы хотим получить вопрос только с ответом, получившим наибольшее количество голосов, нам нужно будет включить результат подзапроса, выбирающего такой ответ.


>>> from django.db.models import OuterRef, Subquery
>>> answer_subquery = Answer.objects.filter(
        question=OuterRef('pk')).annotate(
            upvotes=Count(F('upvoters')
        )
    ).order_by('-upvotes')# What's happening here?
>>> questions = Questions.objects.annotate(
        answer=Subquery(answer_subquery.values('answer')[-1])
    )

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

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

Для положительных голосов ведется отдельная таблица. Можно легко подсчитать группировку по ответам. Для простоты этот запрос пока можно проигнорировать.

SQL может выглядеть примерно так:


# Отсутствуют некоторые подробности о проголосовавших, так как это поле "многие ко многим".
SELECT "question"."id", (
    SELECT "answer"."answer",COUNT("answer.upvoters") as "upvotes" 
    FROM "answer"
    WHERE "answer"."question" = "question"."id"
    GROUP BY 1
    ORDER BY COUNT("answer.upvoters") DESC 
    LIMIT 1
) as "answer" from "question"

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

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


from django.db import connection

def my_custom_sql(self):
    with connection.cursor() as cursor:
        cursor.execute("""
            UPDATE x 
            SET a = 1 
            WHERE bar = %s
        """,[self.a])
        cursor.execute("""
            SELECT foo 
            FROM x 
            WHERE bar = %s
        """, [self.a])
        
        row = cursor.fetchone()

    return row

Объект django.db.connection представляет соединение с базой данных по умолчанию. Чтобы использовать соединение с базой данных, вызовите connection.cursor(), чтобы получить объект курсора. Затем вызовите cursor.execute (SQL, <params>) для выполнения SQL и cursor.fetchone() или cursor.fetchall() для возврата результирующих строк.

Заключение

В этом кратком руководстве мы рассмотрели некоторые основы, которые являются ключевыми для выполнения сложных взломов SQL, а также, наконец, обсудили, как мы можем выполнять пользовательский SQL. Я настоятельно рекомендую просмотреть официальную документацию Django, чтобы получить больше информации о других доступных функциях и приемах, которые предлагает Django ORM, если эта статья не может что-то объяснить. Надеюсь, это помогло, пожалуйста, оставляйте отзывы в случае каких-либо сомнений или отзывов. Спасибо за прочтение!

Вернуться на верх

Как писать сложные запросы в SQL Server

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

Что такое сложный запрос SQL?

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

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

Сложные запросы SQL Server с несколькими операторами SELECT

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

Как создавать сложные запросы с помощью dbForge Studio для SQL Server

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

Эта функциональность доступна в dbForge Studio для SQL Server, мощном инструменте, который включает в себя набор функций для улучшения написания кода SQL и настройки производительности. Среди них функция Query Builder. Его цель — устранить любые трудности, возникающие в процессе создания SQL-запросов, и сделать управление запросами максимально быстрым и простым.

Query Builder помогает вам просматривать структуру запроса и позволяет создавать даже самые сложные запросы с помощью простого перетаскивания и нескольких щелчков мыши. С его помощью можно выполнять множественные соединения и объединять несколько запросов в подзапрос без особых усилий.

Шаг 1. Откройте Query Builder

Чтобы начать построение запросов визуально, откройте dbForge Studio для SQL Server и перейдите на стартовую страницу. Найдите Query Builder в списке инструментов разработки SQL и щелкните, чтобы начать .

Шаг 2. Добавьте таблицы в запрос

Далее вы можете приступить к добавлению таблиц и представлений в запрос. Для этого щелкните нужный узел базы данных в Database Explorer, выберите нужную таблицу (или несколько таблиц) и простым перетаскиванием перенесите ее в область диаграммы запросов. Есть еще один способ сделать то же самое: щелкните правой кнопкой мыши таблицу в Database Explorer и выберите Send to , а затем Query Builder .

Шаг 3. Создайте подзапрос

dbForge Studio для SQL Server позволяет создавать подзапросы в любом предложении инструкции SELECT. Более того, внутри программы каждый подзапрос может иметь другой подзапрос.

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

Шаг 4. Создание соединений JOIN между таблицами

Другой вариант, доступный в dbForge Studio для SQL Server, — это визуальное создание нескольких типов соединений JOIN между таблицами. К ним относятся внутреннее, левое внешнее, правое внешнее и перекрестное соединение. Кроме того, для любого типа соединения можно задать условия повышенной сложности.

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

Шаг 5. Создайте предложение WHERE или HAVING

При построении запроса вы часто намереваетесь отфильтровать или исключить определенные записи из вывода. Самый простой способ сделать это — использовать предложения WHERE и HAVING.

Инструмент имеет интуитивно понятный интерфейс, позволяющий легко создавать предложения WHERE и HAVING. Просто перейдите на соответствующие вкладки dbForge Studio для SQL Server и внесите соответствующие изменения.

Шаг 6. Создайте предложение GROUP BY или ORDER BY

Предложение GROUP BY обычно находится в операторе SELECT и используется для группировки записей в соответствии с заданными параметрами. Предложение ORDER BY помогает сортировать записи в результирующем наборе в порядке возрастания или убывания.

В dbForge Studio вы можете создавать предложения такого типа практически мгновенно. Перейдите на соответствующие вкладки программы и выберите столбцы для сортировки или группировки.

Шаг 7. Просмотрите и выполните запрос

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

Шаг 8. Проанализируйте результат

После того, как вы инициируете выполнение запроса, вы будете уведомлены о том, был ли запрос выполнен успешно или возникли какие-либо ошибки. Если запрос прошел успешно, вы можете проверить и проанализировать результаты.

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

Заключение

Если вы решили построить сложный запрос с несколькими предложениями и условиями, а также подзапросами, помните, что этот процесс не должен быть сложным и утомительным. Функциональность построителя запросов, доступная в dbForge Studio для SQL Server, поможет вам разработать самые сложные запросы и сосредоточиться на результате, а не на процессе написания кода SQL. Используйте интуитивно понятный графический интерфейс, чтобы реализовать свои самые смелые идеи с умом и легко.

  • Автор
  • Последние посты

Dbforge Team

Последние посты от Dbforge Team (см. Все)

  • Oracle Index: Create, Drop, Rename — Руководство с примерами — 6 октября 2022
  • Need dbForge SQL Complete — 30 сентября 2022 г.
  • Продукты Devart становятся победителями конкурса читателей DBTA 2022 — 13 сентября 2022 г.

сложные запросы, dbForge Studio для SQL Server, построитель запросов, sql server

Как написать сложный запрос SELECT

За свою карьеру я много раз слышал такие вещи, как «Как написать сложный запрос SELECT?», «С чего начать?» или же «Этот запрос выглядит таким сложным. Как ты научился писать такие сложные запросы?». В то время как я хотел бы считать себя блестящим умом или гением или добавить что-то вроде «мага запросов» в свои профили в социальных сетях, ну, для этого потребуется не только написание сложного SQL. Поэтому в этой статье я попытаюсь осветить «магию» написания сложных операторов SELECT.

Модель

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

Если у вас нет этих двух в распоряжении, у вас есть 3 варианта:

  • Попросите кого-нибудь, кто создал модель, предоставить документацию (если этот человек доступен). То же самое означает понимание бизнес-логики данных
  • Создайте документацию самостоятельно. Это требует времени, но на самом деле очень полезно, особенно если вы прыгаете посередине. недокументированного проекта
  • Вы всегда можете сделать это без документации, но вы должны быть уверены, что знаете, что делаете. Например. я не рекомендовал бы вам водить машину, тормоза которой я ремонтировал. Я имею в виду, вы можете попробовать, но…

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

Начнем со сложного запроса

На случай, если я пока потратил слишком много слов, давайте напомним себе исходный вопрос — «Как написать сложное ВЫБЕРИТЕ запрос?». И начнем со сложного запроса.

1

2

3

4

5

6

7

8

10

11 0003

12

13

SELECT

country.country_name_eng,

SUM(СЛУЧАЙ, КОГДА call.id НЕ NULL THEN 1 ELSE 0 END) КАК звонки,

AVG(ISNULL(DATEDIFF(SECOND, call.start_time, call.end_time),0 )) AS avg_difference

ИЗ страны

СОЕДИНИТЬСЯ НАЛЕВО city ON city. country_id = country.id

СОЕДИНИТЬСЯ НАЛЕВО customer ON city.id = customer.city_id

СОЕДИНИТЬСЯ НАЛЕВО call ON call.customer_id = customer.id

GROUP BY

country.id,

country.country_name_eng

HAVING AVG(ISNULL(DATEDIFF(SECOND, call.start_time, call.end_time),0)) > (SELECT AVG(DATEDIFF(SECOND, call.start_time, call.end_time)) FROM call)

ORDER BY вызовы DESC , идентификатор страны ASC;

И вот что возвращает запрос:

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

Как написать сложный запрос SELECT и где данные?

Мы вернулись к исходному вопросу. Теперь мы ответим на этот шаг за шагом. Расскажу, каков был желаемый результат запроса (данного нам задания).

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

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

А как определить какие таблицы должны быть? Ответ состоит из двух частей:

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

После этого анализа мы знаем, что должны использовать следующие таблицы: страна , город , клиент и вызов . Если мы хотим использовать их правильно, нам нужно СОЕДИНИТЬ эти таблицы с помощью внешних ключей. Даже без думая об окончательном запросе, теперь мы знаем, что он будет содержать эту часть:

1

2

3

4

5

6

7

ВЫБЕРИТЕ

ИЗ страны

ЛЕВОЕ СОЕДИНЕНИЕ city ON city.country_id = country.id

ЛЕВОЕ СОЕДИНЕНИЕ клиента ON city.id = customer.city_id

ЛЕВОЕ СОЕДИНЕНИЕ call ON call.customer_id = customer.id

…;

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

1

2

3

4

5

6

ВЫБЕРИТЕ

*

ИЗ страны

ЛЕВОЕ СОЕДИНЕНИЕ city ON city.country_id = country.id

ЛЕВОЕ СОЕДИНЕНИЕ клиента ON city.id = customer.city_id

ЛЕВОЕ СОЕДИНЕНИЕ call ON call. customer_id = customer.id;

Я не буду публиковать изображение всего результата, потому что в нем слишком много столбцов. Тем не менее, вы можете проверить это. я всегда советую вам тестировать части ваших запросов. Хотя они не будут отображаться в окончательных результатах, они будут использоваться в фоновом режиме. Протестировав эти части, вы получите представление о том, что происходит в фоновом режиме, и сможете предположить, каким должен быть конечный результат. Но все же нам предстоит ответить на вопрос «Как написать сложный SELECT-запрос?».

Как написать сложный запрос SELECT — записывать части запроса одновременно

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

Я бы начал с этой части «где средняя продолжительность вызова больше, чем средняя продолжительность всех вызовов» . Очевидно, что нам нужно вычислить среднюю продолжительность всех звонков (в секундах). Итак, начнем сделай это.

SELECT AVG(DATEDIFF(SECOND, call.start_time, call.end_time)) ИЗ вызова

Мы объяснили агрегатные функции в предыдущей статье. До сих пор мы не говорили о функциях даты и времени, но достаточно сказать, что Функция DATEDIFF вычисляет разницу в единицах данного периода времени (здесь мы после секунд) между временем начала и временем окончания. Возвращенный результат означает, что средняя продолжительность вызова составила 354 секунды.

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

1

2

3

4

5

6

7

8

10

11

12

SELECT

country. country_name_eng,

SUM(СЛУЧАЙ, КОГДА call.id НЕ NULL THEN 1 ELSE 0 END) КАК звонки,

AVG(ISNULL(DATEDIFF(SECOND, call.start_time, call.end_time),0 )) AS avg_difference

ИЗ страны

ЛЕВОЕ СОЕДИНЕНИЕ город ВКЛ city.country_id = country.id

ЛЕВОЕ СОЕДИНЕНИЕ клиент ВКЛ city.id = customer.city_id

ЛЕВОЕ СОЕДИНЕНИЕ вызов ВКЛ call.customer_id = customer.id

ГРУППА ПО

23 .id,

country.country_name_eng

ORDER BY звонки DESC, country.id ASC;

Здесь я хотел бы отметить две вещи:

  • SUM(CASE WHEN call.id NOT NULL THEN 1 ELSE 0 END) — суммируются только существующие вызовы. Поскольку мы использовали LEFT JOIN, мы также присоединимся к странам без всякого звонка. Если бы мы использовали COUNT, для стран без вызова было бы возвращено значение 1, а мы хотим, чтобы там было 0 (мы хотим видеть эту информацию)
  • AVG(ISNULL(DATEDIFF(SECOND, call. start_time, call.end_time),0)) — очень похож на ранее упомянутый AVG. Разница здесь в том, что я использовал ISNULL(…,0). Это просто проверяет, является ли вычисленное значение IS NULL, и если это так, заменяет его на 0. Вычисленное значение может быть NULL, если данных нет (мы использовали LEFT JOIN)

Давайте посмотрим, что возвращает этот запрос.

«Как написать сложный запрос SELECT?» -> Теперь мы очень близки к завершению нашего запроса и очень близки к этому ответу.

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

1

2

3

4

5

6

7

8

10

11

12

13

14

15

16

— запрос возвращает сводку по звонкам для стран со средней продолжительностью звонка > средней продолжительности звонка по всем звонкам Вызовы AS,

    AVG(ISNULL(DATEDIFF(SECOND, call. start_time, call.end_time),0)) AS avg_difference

ИЗ страны

— мы использовали левое соединение, чтобы включить также страны без какого-либо звонка .customer_id = customer.id

GROUP BY

    country.id,

    country.country_name_eng

— отфильтровать только страны со средней продолжительностью звонка > средней продолжительности звонка для всех звонков

(

HAVING(DATEDIFFULL(ISNULL(ISNULL) SECOND, call.start_time, call.end_time),0)) > (SELECT AVG(DATEDIFF(SECOND, call.start_time, call.end_time)) FROM call)

ORDER BY вызывает DESC, country.id ASC;

Вы можете увидеть результат запроса на картинке ниже.

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

Комментарии — важная вещь не только в базах данных, но и в программировании в целом. Добавив эти 3 строки комментариев, запрос должен стать намного более читабельным. Даже тот, кто впервые смотрит на этот запрос, увидит, что вы сделали и почему. Этот кто-то может быть даже вами, если вы посмотрите на код, который вы написали некоторое время назад. Хотя на написание этих комментариев уходит некоторое время, не поленитесь и сделайте это. Вы, вероятно, сэкономите гораздо больше времени при повторном просмотре старых запросов/кода.

Давайте завершим все

Итак, вопрос был — «Как написать сложный SELECT-запрос?». Хотя простого ответа нет, я бы предложил следующие шаги:

  • Думайте об этом как о кирпичиках LEGO и создавайте запрос таким образом. Относитесь к сложным деталям как к черным ящикам — они верните то, что им нужно, и вы напишете (и включите в основной запрос) их позже
  • Определите все таблицы, которые вам понадобятся в запросе
  • Соедините таблицы, содержащие данные, которые необходимо отобразить, или данные, используемые в части WHERE запроса.
  • Отобразите все данные, чтобы проверить, все ли вы правильно соединили, и увидеть результат такого запроса.
  • Создавайте все подзапросы отдельно. Проверьте их, чтобы увидеть, возвращают ли они то, что должны. Добавьте их в основной запрос
  • Тестируйте все
  • Добавить комментарии

Не могли бы вы дать нам свой ответ на вопрос «Как написать сложный запрос SELECT?». Какой подход вы использовали?

Содержание

Изучение SQL: операции CREATE DATABASE & CREATE TABLE
Изучение SQL: ВСТАВИТЬ В ТАБЛИЦУ
Изучение SQL: первичный ключ
Изучение SQL: внешний ключ
Изучение SQL: инструкция SELECT
Изучение SQL: ВНУТРЕННЕЕ СОЕДИНЕНИЕ и ЛЕВОЕ СОЕДИНЕНИЕ
Изучение SQL: сценарии SQL
Изучение SQL: типы отношений
Изучение SQL: объединение нескольких таблиц
Изучение SQL: агрегатные функции
Изучение SQL: как написать сложный запрос SELECT
Изучение SQL: база данных INFORMATION_SCHEMA
Изучение SQL: типы данных SQL
Изучение SQL: теория множеств
Изучение SQL: пользовательские функции
Изучение SQL: определяемые пользователем хранимые процедуры
Изучение SQL: представления SQL
Изучение SQL: триггеры SQL
Изучение SQL: практика SQL-запросов
Изучение SQL: примеры запросов SQL
Изучение SQL: создание отчета вручную с помощью SQL-запросов
Изучение SQL: функции даты и времени SQL Server
Изучение SQL: создание отчетов SQL Server с использованием функций даты и времени
Изучение SQL: сводные таблицы SQL Server
Изучение SQL: экспорт SQL Server в Excel
Изучение SQL: введение в циклы SQL Server
Изучение SQL: курсоры SQL Server
Изучение SQL: передовые методы SQL для удаления и обновления данных
Изучение SQL: соглашения об именах
Изучение SQL: задания, связанные с SQL
Изучение SQL: неэквивалентные соединения в SQL Server
Изучение SQL: SQL-инъекция
Изучение SQL: динамический SQL
Изучение SQL: как предотвратить атаки SQL Injection
  • Автор
  • Последние сообщения

Эмиль Дркусич

Эмиль — специалист по базам данных с более чем 10-летним опытом работы во всем, что связано с базами данных. В разные годы он работал в сфере информационных технологий и финансов, а сейчас работает фрилансером.

Его прошлые и настоящие занятия варьируются от проектирования баз данных и кодирования до обучения, консультирования и написания статей о базах данных. Также не забыть, BI, создание алгоритмов, шахматы, филателия, 2 собаки, 2 кошки, 1 жена, 1 ребенок…

Вы можете найти его на LinkedIn

Просмотреть все сообщения Эмиля Дркусика

Последние сообщения Эмиля Дркусика (посмотреть все)

Как писать сложные запросы SQL

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

Предоставил: Aadish Jain

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

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

  1. Когда есть 3-4 таблицы для объединения по разным атрибутам.
  2. Когда есть неопределенность в отношении того, какие условия соединения (внутреннее соединение, внешнее соединение, правое соединение, левое соединение) следует использовать в каком случае.
  3. Когда требуемый столбец не присутствует непосредственно в базе данных, но его необходимо получить из 2-3 столбцов или с помощью математических функций, таких как среднее, максимальное, минимальное и т. д.
  4. Когда существует неопределенность в отношении использования некоторых необычных условий, например группировать, иметь, заказывать.

В этой статье я попытаюсь рассказать о «волшебстве» написания сложных операторов SELECT.

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

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

Мы должны использовать правильный отступ, потому что только запись и запуск не важны. Он должен быть легко читаем другим человеком. Поместите каждое выбираемое поле в отдельную строку и поместите каждую новую объединенную таблицу в отдельную строку, а каждый элемент предложения «ГДЕ» — в отдельную строку. Используйте осмысленные псевдонимы для таблиц, чтобы улучшить читаемость. Скорее всего, вам придется ссылаться на свои таблицы несколько раз в запросе, и если вы работаете с чужой базой данных с их соглашением об именах, имена таблиц могут содержать избыточную информацию. Например, «Сведения о сотруднике» — так что вы называете такую ​​таблицу «ED», имя таблицы «Заголовок заказа» может иметь псевдоним «OH» и т. д.

Рисунок 1: Схема для набора данных заказов

Постановка проблемы заключается в том, что нам необходимо:

Написать запрос для отображения order_id, идентификатора клиента и полного имени клиента вместе с (product_quantity) в качестве общего количества товаров, отгруженных для идентификаторов заказов > 10060, для клиентов, купивших более 15 товаров на отгруженный заказ.

Здесь мы можем понять, что требуются таблицы : online_customer, order_header, order_items, которые могут иметь псевдонимы C, OH и OI соответственно.

Начнем: 

Выберите запрос, указав необходимые столбцы из каких таблиц.

Итак, orderID можно получить из заголовка заказа или таблицы order_id. Customer_id и имя клиента можно получить из таблицы клиентов.

Количество продукта для каждого заказа доступно в таблице Order Items. Таким образом, запрос будет таким:

.
ВЫБЕРИТЕ OI.ORDER_ID,C.CUSTOMER_ID,CONCAT(C.CUSTOMER_FNAME," ",C.CUSTOMER_LNAME) AS 'CUSTOMER_FULL_NAME', SUM(OI.PRODUCT_QUANTITY) AS 'ОБЩЕЕ КОЛИЧЕСТВО'
 

Теперь мы видим, что нам нужно найти общие порядки из всех трех таблиц, поэтому мы должны использовать здесь INNER JOIN.

Элементы заказа и заголовок заказа имеют общий идентификатор Order_ID, а онлайн-клиенты и заголовок заказа имеют идентификатор клиента в качестве общего ключа поля. Поэтому мы будем использовать условия соединения соответственно.

ВЫБЕРИТЕ OI.ORDER_ID,C.CUSTOMER_ID,CONCAT(C.CUSTOMER_FNAME," ",C.CUSTOMER_LNAME) AS 'CUSTOMER_FULL_NAME',
SUM(OI.PRODUCT_QUANTITY) AS 'ОБЩЕЕ КОЛИЧЕСТВО' ОТ online_customer C INNER JOIN ORDER_HEADER OH ON
C. CUSTOMER_ID = OH.CUSTOMER_ID INNER JOIN order_items OI ON OH.ORDER_ID = OI.ORDER_ID
 

Теперь задача состоит в том, чтобы получить все эти данные для идентификаторов заказов> 10060, чтобы мы могли понять, что нам нужно поместить предложение where, чтобы отфильтровать заказы с идентификатором заказа <= 10006. Также статус заказа должен быть Отгружен в заголовке заказа. стол.

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

ВЫБЕРИТЕ OI.ORDER_ID,C.CUSTOMER_ID,CONCAT(C.CUSTOMER_FNAME," ",C.CUSTOMER_LNAME) AS 'CUSTOMER_FULL_NAME',
SUM(OI.PRODUCT_QUANTITY) AS 'ОБЩЕЕ КОЛИЧЕСТВО' ОТ online_customer C INNER JOIN ORDER_HEADER OH ON
C.CUSTOMER_ID = OH.CUSTOMER_ID INNER JOIN order_items OI ON OH.ORDER_ID = OI.ORDER_ID
ГДЕ OH.ORDER_ID > 10060 И OH.ORDER_STATUS = «Отправлено»
 

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

Итак, здесь, в нашем примере, мы должны вычислить сумму количества продуктов для всех продуктов, заказанных с определенным OrderID, поэтому мы будем использовать здесь GROUPBY ORDER_ID.

Таким образом, обновленный запрос будет следующим:

ВЫБЕРИТЕ OI.ORDER_ID,C.CUSTOMER_ID,CONCAT(C.CUSTOMER_FNAME," ",C.CUSTOMER_LNAME) AS 'CUSTOMER_FULL_NAME',
SUM(OI.PRODUCT_QUANTITY) AS 'ОБЩЕЕ КОЛИЧЕСТВО' ОТ online_customer C INNER JOIN ORDER_HEADER OH ON
C.CUSTOMER_ID = OH.CUSTOMER_ID INNER JOIN order_items OI ON OH.ORDER_ID = OI.ORDER_ID
ГДЕ OH.ORDER_ID > 10060 И OH.ORDER_STATUS = ГРУППА «Отправлено» ПО OI.ORDER_ID
 

Если нам нужно задать условия для агрегированных данных, то они не могут быть обработаны предложением WHERE , и мы должны использовать Пункт HAVING для того же.