MySQL — сложные запросы

Привет. Стал я тут писать одно Web-приложение и столкнулся с тем что на вывод одной таблице у меня получается около 4 запрос в БД. Если делать мини сервис с мелкой посещаемостью, то нагрузка как бы не о чем. А вот если людей будет уже около 2000 тысяч хотя бы в сутки, то запросы растут с геометрической прогрессией.

Чтобы не нагружать мой сервер, решил я более глубоко погрузится в MySQL и выяснил, что можно составлять сложные запросы к Базе Данных(БД). Т.е. было 4 select к БД, а стал один с вложенными запросами и join`ами.

К тому же сложные запросы MySQL помогут сократить код логики. Раньше было 4 запроса и соответственно получали 4 массива, каждый нужно было обойти, придать ему нужный вид, дальше объединить его с другими. А сейчас получается один запрос и один массив, все.

Задача

Возьмем абстрактную задачу: Вывести курс ЦБ на страницу.
Выводим следующее:

  1. Даллар США (это название валюты на русском).
  2. USD (это название валюты на английском).
  3. Текущая дата.
  4. Значение валюты.
  5. Вчерашняя дата.
  6. Значение валюты.
  7. Колонка разность (отянть вчера от сегодня).

И так представим, что БД у нас построена по правилам «Трех нормальных форм». Т.е. 1 и 2 пункт из списка выше хранится в одной таблице, 3-6 хранятся данные в другой таблице. А 7 пункт вообще вычисляется средствами MySql.

Сам код запроса

Запрос будет выглядеть следующем образом.

SELECT 
   r.id_name_currency,
   r.value,
   yesterday.value,
   r.date,
   yesterday.date,
   pc.name_currency_en,
   pc.name_currency_ru,
   (yesterday.value - r.value)
FROM 
   parser_all_exchange_rates r
   JOIN 
   (
      SELECT 
         rr.date,
         rr.value,
         rr.id_name_currency
      FROM 
         parser_all_exchange_rates rr
      WHERE 
         rr.id_name_banks = 233 AND
         rr.date = CURRENT_DATE() - INTERVAL 1 DAY 
      
   ) yesterday
   JOIN parser_name_currencies pc ON r.id_name_currency = pc.id
WHERE 
   r.id_name_banks = 233 AND
   r.date = CURRENT_DATE() AND
   yesterday.id_name_currency = r.id_name_currency

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

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

Нюансы

А как же без них.

FROM
   parser_all_exchange_rates r,
   (
      SELECT 
         rr.date,
         rr.value,
         rr.id_name_currency
      FROM 
         parser_all_exchange_rates rr
      WHERE 
         rr.id_name_banks = 233 AND
         rr.date = CURRENT_DATE() - INTERVAL 1 DAY 
      
   ) yesterday
   
   INNER JOIN parser_name_currencies pc ON r.id_name_currency = pc.id

Если посмотреть на код выше, то после from идет указатель на имя таблицы, в которой мы ищем информацию, затем идет в скобках следующая таблица, после скобок ей присваивается имя  yesterday и затем указываем join. Если написать так, то будет синтаксическая ошибка.

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

Необязательно писать INNER JOIN, можно просто JOIN.  СУБД по умолчанию выполнить именно внутреннее соединение.

Будут вопросы пишите в комментариях.

Предыдущая
База данныхУстановка Redis Centos 8
Помогла статья? Оцените её
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд
Оценок: 1
Загрузка...
Добавить комментарий

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