На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! информация о разделе
user posted imageДанный раздел предназначается исключительно для обсуждения вопросов использования языка запросов SQL. Обсуждение общих вопросов, связанных с тематикой баз данных - обсуждаем в разделе "Базы данных: общие вопросы". Убедительная просьба - соблюдать "Правила форума" и не пренебрегать "Правильным оформлением своих тем". Прежде, чем создавать тему, имеет смысл заглянуть в раздел "Базы данных: FAQ", возможно там уже есть ответ.

Модераторы: Akina
  
> Как работают вычисления в SQL?
    Здравствуйте.
    Работаю с базой данный через PhpMyAdmin.
    В нем можно отправлять SQL запросы к базе и в интерфейсе PhpMyAdmin видеть результат. Заинтересовали расчеты с помощью SQL. Помогите с ними разобраться.

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

    Можно ли с помощью SQL посчитать сумму за каждый заказ умножив
    (количество проданного товара)*(стоимость товара за штуку)?

    Где в таком случае выведется результат произведения?
    Будет создан абстрактный (временный) столбец, где выведутся произведения для каждого заказа?
    Объясните, пожалуйста, как это работает.

    --

    Пример 2.
    Есть таблицы с полями
    - Номер заказа
    - Статус заказа
    - Дата время наступления статуса

    Строка 1:
    - Номер заказа: "123"
    - Статус заказа: "Создан"
    - Дата время наступления статуса: "01.12.2023"

    Строка 2:
    - Номер заказа: "123"
    - Статус заказа: "Завершен"
    - Дата время наступления статуса: "03.12.2023"

    Нужно посчитать с помощью SQL сколько дней для Заказа "123" прошло между статусам "Создан" и "Завершен".
    Т.е. "03.12.2023" - "01.12.2023" = 2дня
    Можно ли это посчитать через SQL?
    Вопрос аналогичный, где будет выведен результат?
    Будет создана абстрактная (временная) таблица в которой будут выведены
    - Номер заказа
    - Количество дней между прошло между статусам "Создан" и "Завершен".
    ??

    user posted image
    Сообщение отредактировано: rownong@yandex.ru -
      Цитата rownong@yandex.ru @
      Можно ли это посчитать через SQL?

      Конечно можно. Для этого тебе нужно сделать соединение таблицы с самой себя. Условие соединения - что номера заказов совпадают, и у первой таблицы в поле статуса заказа "создан", и у второй "завершен". В этом запросе в блоке SELECT указываешь первым полем - номер заказа (первой или присоединяемой таблицы - без разницы, т.к. они равны), вторым полем используешь функцию с постфикcом AS days. Этим самым ты переназовешь второй столбец. Функцию ищи в документации, которая рассчитывает разницу в днях. Если я не ошибаюсь - в MySQL это DATEDIFF. В PostgreSQL используй что-то типа:

      ExpandedWrap disabled
        (timestamp2::date - timestamp1::date) AS days


      Добавлено
      Цитата rownong@yandex.ru @
      Вопрос аналогичный, где будет выведен результат?
      Будет создана абстрактная (временная) таблица в которой будут выведены
      - Номер заказа
      - Количество дней между прошло между статусам "Создан" и "Завершен".
      ??

      Будет создан результат, который будет выведен в интерфейс phpMyAdmin, и никуда не будет записан. Если нужно его куда-то сохранить - копируй из интерфейса копипастой. Или создай заранее нужную таблицу в БД и в нее произведи запись результата запроса.
        Цитата rownong@yandex.ru @
        Где в таком случае выведется результат произведения?

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

        Например, запрос может выглядеть так:
        ExpandedWrap disabled
          SELECT table1.name1, table2.name2 AS name3, table1.name4 * table2.name5 AS name6
          FROM ...

        Соответственно после связывания исходных таблиц в соответствии в секцией FROM, фильтрации в соответствии со WHERE и сортировкой в соответствии с ORDER BY будет возвращён набор записей. Он будет состоять из трёх полей с именами name1, name3 и name6, первые два будут содержать неизменённые значения указанных полей исходных таблиц, третье - произведение указанных полей.
        Сообщение отредактировано: Akina -
          Цитата
          В запросе, который описывает задание серверу, указывается, какие поля нужно вернуть, и с помощью каких выражений следует получать для них значения. Можно вывести поле исходной таблицы без изменения, можно его при выводе переименовать, можно на основе нескольких полей написать вычисляющее выражение и дать ему имя...

          Получается когда делаем SQL запрос, чтобы соединить 2 таблицы можем в результате скрывать (не выводить) определённые столбцы? Вернее, выводить только нужны столбцы из обоих таблиц

          Добавлено
          Если есть например 10 менеджеров по продажам, мы можем в результате SQL запроса вывести не 10 строка с суммой продажи каждого менеджера за месяц, а 1 строк с суммой продаж всех менеджеров за месяц?
          Сообщение отредактировано: rownong@yandex.ru -
            Цитата rownong@yandex.ru @
            Получается когда делаем SQL запрос, чтобы соединить 2 таблицы можем в результате скрывать (не выводить) определённые столбцы? Вернее, выводить только нужны столбцы из обоих таблиц

            Да.
            Цитата rownong@yandex.ru @
            Если есть например 10 менеджеров по продажам, мы можем в результате SQL запроса вывести не 10 строка с суммой продажи каждого менеджера за месяц, а 1 строк с суммой продаж всех менеджеров за месяц?

            Можем. Есть несколько вариантов. Первый - используй фильтрацию запросов оператором WHERE чтобы получить одну нужную строку, либо пробуй использовать оператор LIMIT с аргументом 1. Во втором случае скорее всего нужно будет прибегнуть заранее к сортировке строк результата, ибо лимит только "обрежет" остальные строки из результата. А без предварительной сортировки это будет недетерминированный результат.

            Хотя, суммируя все продажи, мы реально должны получить одну строку без всяких телодвижений типа WHERE и LIMIT.
              Цитата rownong@yandex.ru @
              Получается когда делаем SQL запрос, чтобы соединить 2 таблицы можем в результате скрывать (не выводить) определённые столбцы? Вернее, выводить только нужны столбцы из обоих таблиц

              Выводить нужно (не можно, а именно нужно) только то, что реально требуется. Если нужны только результаты вычисления каких-то выражений - в выходном наборе должны быть только они. SELECT * в рабочей версии приложения пишут исключительно идиоты (да, вот настолько безальтернативно) - даже если действительно нужны все поля, следует их перечислять по одному. Или идти учить матчасть по нормализации данных.

              Цитата rownong@yandex.ru @
              Если есть например 10 менеджеров по продажам, мы можем в результате SQL запроса вывести не 10 строка с суммой продажи каждого менеджера за месяц, а 1 строк с суммой продаж всех менеджеров за месяц?

              Продажа отдельного менеджера и продажа всех менеджеров - это разные уровни группировки. Поэтому сама фраза не имеет смысла - нужно ведь либо то, либо другое. А если вдруг надо всё это одновременно (программист не умеет заставить клиентскую часть выводить итоги), то есть GROUP BY WITH ROLLUP/CUBE. Нереляционно, но если по другому не умеешь - пусть его. Это ж потом не SQL-серверу трахаться, а клиентской части, её не жалко.
                Цитата Akina @
                SELECT * в рабочей версии приложения пишут исключительно идиоты (да, вот настолько безальтернативно) - даже если действительно нужны все поля, следует их перечислять по одному

                Согласен полностью. Но только с учетом именно рабочей версии. В процессе написания скрипта и его отладки SELECT * вполне допустимо использовать, иногда это немного экономит время. ИМХО.
                  SELECT * можно писать в рабочем коде. Вот MS SQL пример:
                  ExpandedWrap disabled
                    IF EXISTS(SELECT * …

                  Есть еще по крайней мере один случай, когда нельзя перечислять поля, а надо писать SELECT * в рабочем коде.
                    Цитата MIF @
                    надо писать SELECT * в рабочем коде

                    Хм...Это с какого такого перепугу? :P
                      Цитата MIF @
                      SELECT * можно писать в рабочем коде. Вот MS SQL пример:

                      Вас спасает только то, что MS SQL достаточно умный. И знает, что в EXISTS сами значения полей не нужны, и лезть за ними в тело таблицы не требуется. Но вот формально - такой код требует метнуться за значениями полей, а потому SELECT {const} разумнее и логичнее.

                      Цитата MIF @
                      Есть еще по крайней мере один случай, когда нельзя перечислять поля, а надо писать SELECT * в рабочем коде.

                      Хотелось бы конкретики. Я пока о таких случаях не слышал - за исключением ситуации, когда необходимость грести всё подряд определяется или отставанием клиента, или мультиверсионностью БД.
                        Еще подскажите:

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

                        2. Какой оператор нужно использовать, чтобы использовать фильтр типа "содержит"?
                        Например выбрать все записи из table1, в которых поле log содержит текст "395948"

                        Пример значений поля log
                        {"items_data":[{"item_sid":"7069294","qty":1}],"contact_phone":"79778681007","contact_name":"u0421u043eu0431u0441u0442u0432u0435u043du043du0430u044f u0437u0430u044fu0432u043au0430","contact_email":"service@yandex.ru","jp_purchase_id":"395948"}

                        {"items_data":[{"item_sid":"2388062","qty":2}],"contact_phone":"79778681007","contact_name":"u0421u043eu0431u0441u0442u0432u0435u043du043du0430u044f u0437u0430u044fu0432u043au0430","contact_email":"service@yandex.ru","jp_purchase_id":"395948"}

                        Интересует как это указывать в запросе и в фильтре PhpMyAdmin.
                        user posted image
                        user posted image
                          Цитата rownong@yandex.ru @
                          1. При SQL запросе, когда создаем абстрактные (не существующие) поле (столбцы) можно ли кроме присвоения им имен, также добавлять комментарии, на время просмотра SQL запроса?

                          Нет.

                          Цитата rownong@yandex.ru @
                          2. Какой оператор нужно использовать, чтобы использовать фильтр типа "содержит"?

                          Показанные примеры не относятся к типу "содержит". Это типичный случай "равно" (использован синтаксис MySQL):
                          ExpandedWrap disabled
                            WHERE log->>"$.jp_purchase_id" = '395948'
                            Цитата Akina @
                            Цитата rownong@yandex.ru @
                            1. При SQL запросе, когда создаем абстрактные (не существующие) поле (столбцы) можно ли кроме присвоения им имен, также добавлять комментарии, на время просмотра SQL запроса?

                            Нет.

                            Цитата rownong@yandex.ru @
                            2. Какой оператор нужно использовать, чтобы использовать фильтр типа "содержит"?

                            Показанные примеры не относятся к типу "содержит". Это типичный случай "равно" (использован синтаксис MySQL):
                            ExpandedWrap disabled
                              WHERE log->>"$.jp_purchase_id" = '395948'

                            Спасибо!
                              Подскажите, правильно понимаю, что результатом SQL запроса могут быть:
                              1. Реальная таблица из БД.
                              2. Абстрактная таблица (с несуществующими столбцами, но которые создаем в момент запроса)
                              3. Число (например результат расчетов). Т.е. просто одно число (без таблиц и столбцов), которое получаем в результате.
                              ??
                                Цитата rownong@yandex.ru @
                                Подскажите, правильно понимаю, что результатом SQL запроса могут быть:
                                1. Реальная таблица из БД.
                                2. Абстрактная таблица (с несуществующими столбцами, но которые создаем в момент запроса)
                                3. Число (например результат расчетов). Т.е. просто одно число (без таблиц и столбцов), которое получаем в результате.

                                Не совсем правильно. Результатом SQL запроса не может быть ни реальная таблица из БД, ни абстрактная таблица, и ни число. Ибо результатом SQL запроса может быть только сам результат SQL запроса :)

                                Другое дело, что может содержать этот результат. А он может содержать:

                                1. Значения всех или отдельных полей (столбцов) реальной таблицы или таблиц из БД
                                2. Значения полей (столбцов), получаемых в результате вычислений, обращений к VIEW или хранимым процедурам
                                3. Значения полей (столбцов), заданных константой

                                Последний вариант, скажем так, сильно менее распространён. Как правило используется в подзапросах. Ибо в финальном запросе указывать поле, содержащее константу, по факту - бессмысленно.
                                  Цитата Akina @
                                  Нет.

                                  Он скорее всего некорректно задал вопрос :lol: Возможно речь шла о формировании "комментария" (по факту обычного поля), а-ля:

                                  ExpandedWrap disabled
                                    SELECT
                                      name AS Name,
                                      cnt AS Cnt ,
                                      CASE WHEN cnt > 100500 THEN 'дофига' ELSE 'так себе' END AS Comment;


                                  Хотя - это только мои догадки.
                                    Цитата Majestio @
                                    Цитата Akina @
                                    Нет.

                                    Он скорее всего некорректно задал вопрос :lol: Возможно речь шла о формировании "комментария" (по факту обычного поля), а-ля:

                                    ExpandedWrap disabled
                                      SELECT
                                        name AS Name,
                                        cnt AS Cnt ,
                                        CASE WHEN cnt > 100500 THEN 'дофига' ELSE 'так себе' END AS Comment;


                                    Хотя - это только мои догадки.

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

                                    ExpandedWrap disabled
                                      CREATE TABLE IF NOT EXISTS `BIO` (`id` INT PRIMARY KEY COMMENT 'Main key', `name` VARCHAR(64) COMMENT 'Имя', `sername` VARCHAR(64) COMMENT 'Фамилия', `male` INT(1) COMMENT 'Пол мужской?')


                                    Вот об этих комментариях он спрашивал

                                    https://dev.mysql.com/doc/refman/8.0/en/create-table.html
                                      Цитата macomics @
                                      Вот об этих комментариях он спрашивал

                                      https://dev.mysql.com/doc/refman/8.0/en/create-table.html

                                      А, понятно :good:
                                        Цитата rownong@yandex.ru @
                                        Подскажите, правильно понимаю, что результатом SQL запроса могут быть:
                                        1. Реальная таблица из БД.
                                        2. Абстрактная таблица (с несуществующими столбцами, но которые создаем в момент запроса)
                                        3. Число (например результат расчетов). Т.е. просто одно число (без таблиц и столбцов), которое получаем в результате.
                                        ??

                                        Совершенно неправильно.

                                        Есть запросы, которые возвращают набор данных. Т.е. которые возвращают результат выборки/расчёта. Даже если результатом является единственная запись с единственным полем (то, что тебе кажется "просто числом"). Даже если результатом является пустой, не содержащий ни одной записи, набор.

                                        И есть запросы, которые НЕ возвращают набор данных. Это запросы, которые модифицируют данные (если диалект не поддерживает RETURNING или если он не использован), а также запросы, которые работают с метаданными. Такие запросы возвращают статус выполненного запроса и, возможно, дополнительную информацию по его выполнению (например, запрос на обновление возвращает как общее количество записей, соответствующих условиям отбора, так и количество фактически обновлённых записей, т.е. в которых новое значение отличается от старого).

                                        Кроме того, выполнение абсолютно любого запроса может привести к ошибке - в этом случае возвращается код ошибки и дополнительная информация по ней.
                                          Цитата Akina @
                                          Совершенно неправильно.

                                          Есть запросы, которые возвращают набор данных. Т.е. которые возвращают результат выборки/расчёта. Даже если результатом является единственная запись с единственным полем (то, что тебе кажется "просто числом"). Даже если результатом является пустой, не содержащий ни одной записи, набор.

                                          И есть запросы, которые НЕ возвращают набор данных. Это запросы, которые модифицируют данные (если диалект не поддерживает RETURNING или если он не использован), а также запросы, которые работают с метаданными. Такие запросы возвращают статус выполненного запроса и, возможно, дополнительную информацию по его выполнению (например, запрос на обновление возвращает как общее количество записей, соответствующих условиям отбора, так и количество фактически обновлённых записей, т.е. в которых новое значение отличается от старого).

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

                                          Не согласен, потому как речь шла именно о запросах по получению данных. Другие запросы, модифицирующие прикладные данные, системную информацию - об этом не шла речь. Равно как и о запросах с ошибкой.
                                            Цитата rownong@yandex.ru @
                                            3. Число (например результат расчетов). Т.е. просто одно число (без таблиц и столбцов), которое получаем в результате.
                                            ??

                                            По этому вопросу в итоге непонял, результат SQL моежет быть только 1 число - результат вычислений?
                                              Цитата rownong@yandex.ru @
                                              По этому вопросу в итоге непонял, результат SQL моежет быть только 1 число - результат вычислений?

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

                                              Так надеюсь понятнее.
                                                Цитата rownong@yandex.ru @
                                                По этому вопросу в итоге непонял, результат SQL моежет быть только 1 число - результат вычислений?

                                                Нет.

                                                Как уже выше сказано, это будет набор записей. Сам набор будет состоять из одной записи, а структура набора (и соответственно этой одной записи) будет состоять из одного поля. Как итог - весь набор записей будет содержать ровно 1 запись * 1 поле = 1 значение. Но набор записей содержит ещё кучу метаданных - количество полей (одно), имя этого одного поля, тип его данных, количество записей (одна)...

                                                Соответственно обратиться к этому набору как к скалярному значению - нельзя. Хорошо, если при обращении будет выполнено неявное приведение к скалярному типу - то есть удалена метаинформация об имени поля и типе его данных и пр... но надеяться на это неразумно, да и вероятность существования в синтаксисе такого неявного приведения весьма мала. Например, тот же MySQL вроде бы делает это с лёгкостью - ага, как бы не так! для того, чтобы он преобразовал, надо выражение-запрос обернуть скобками, иначе syntax error.
                                                Сообщение отредактировано: Akina -
                                                  Подскажите в SQL запросе возможно построить абстрактную (виртуальную) таблицу следующего вида, где показатели идут не в столбцах а в строках? Т.е. из разных таблиц собрать временные столбцы и строки такого вида как на скрине. Грубо говоря мини-дашборд.
                                                  user posted image
                                                    Цитата rownong@yandex.ru @
                                                    Подскажите в SQL запросе возможно построить абстрактную (виртуальную) таблицу

                                                    Нет. Применительно к SQL такого понятия как "абстрактная (виртуальная) таблица" - не существует.

                                                    Используйте корректную технически грамотную терминологию.
                                                      Цитата rownong@yandex.ru @
                                                      Подскажите в SQL запросе возможно построить абстрактную (виртуальную) таблицу следующего вида, где показатели идут не в столбцах а в строках? Т.е. из разных таблиц собрать временные столбцы и строки такого вида как на скрине. Грубо говоря мини-дашборд.
                                                      user posted image

                                                      А что по поводу этого вопроса? Такое решение реально сделать?
                                                        Цитата rownong@yandex.ru @
                                                        А что по поводу этого вопроса? Такое решение реально сделать?

                                                        Абстрактных (виртуальных) таблиц в SQL не существует, но есть VIEW (представления), которые реализуют твои потребности по данному вопросу.
                                                        Материала по этому в сети полно. Навскидку, почитай вот эту статью. Статья более-менее норм, имхо.
                                                          Еще подскажите, создавая временные (виртуальные) поля (столбцы) в результате SQL запроса, можно им имена давать не на латинице, а на кириллице и с пробелами?
                                                          Сообщение отредактировано: rownong@yandex.ru -
                                                            ExpandedWrap disabled
                                                              SELECT
                                                                  id as 'идентификатор',
                                                                  name as 'имя',
                                                                  sername as 'фамилия',
                                                                  extname as 'отчество',
                                                                  birthday as 'дата рождения'
                                                               FROM BIOData;
                                                            Что мешает попробовать? Это на MSSQL - работает.

                                                            https://sqliteonline.com/

                                                            Для тренировки и уменьшения количества вопросов
                                                              Цитата macomics @
                                                              ExpandedWrap disabled
                                                                SELECT
                                                                    id as 'идентификатор',
                                                                    name as 'имя',
                                                                    sername as 'фамилия',
                                                                    extname as 'отчество',
                                                                    birthday as 'дата рождения'
                                                                 FROM BIOData;
                                                              Что мешает попробовать? Это на MSSQL - работает.

                                                              https://sqliteonline.com/

                                                              Для тренировки и уменьшения количества вопросов

                                                              Отлично! Спасибо!
                                                                Попробовал просто на кириллице одинарные слова или несколько через нижнее подчеркивание, все ок.
                                                                А вот когда через пробел слова, даже в кавычках вся фраза, то заглючивает SQL запрос.
                                                                  Подскажите, если есть столбце с полем артикул и в каждой строке перед артикулом приставка "1-" (например 1-23442242), то как вырезать эту приставку "1-" SQL-ем чтобы далее производить вычисления чистым артикулом?
                                                                    Цитата rownong@yandex.ru @
                                                                    как вырезать эту приставку "1-" SQL-ем

                                                                    Зависит от СУБД и даже точной версии - везде свои встроенные строковые функции.
                                                                      Цитата Akina @
                                                                      Цитата rownong@yandex.ru @
                                                                      как вырезать эту приставку "1-" SQL-ем

                                                                      Зависит от СУБД и даже точной версии - везде свои встроенные строковые функции.

                                                                      MySQL
                                                                        https://dev.mysql.com/doc/refman/8.0/en/str...function_substr
                                                                        Сообщение отредактировано: macomics -
                                                                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                        0 пользователей:


                                                                        Рейтинг@Mail.ru
                                                                        [ Script execution time: 0,0849 ]   [ 15 queries used ]   [ Generated: 27.04.24, 10:38 GMT ]