Ответы пользователя по тегу MySQL
  • Как оптимально спроектировать таблицы в бд?

    LaRN
    @LaRN
    Senior Developer
    Я бы за основу взял устройство ЕСКД-шной спецификации (там есть все необходимое).

    Например так:
    Таблица содержащую описание детали(это там, где короб/вал и прочие детали.)
    tEntity (id, Name)

    Таблица содержащая параметры данной детали(это там где размеры детали и прочее)
    tEntityParam(id, EntityID, ParamType, ParamValue)
    Тут ParamType это тип параметра (длина/ширина/высота/марка стали...) - возможно для типов потребуется завести отдельную таблицу с описанием.
    А ParamValue значение этого параметра.

    Таблица описание типа (он же сборка - набор из нескольких деталей):
    tAssemblyType(id, Name, EntityID, Quantity)
    В этой таблице описываем из каких деталей (тип и количество - по сути спецификация) состоит сборка.

    Таблица описание изделия (Возможно что изделие включает в себя несколько сборок):
    tOrder(id, AssemblyTypeID, Name, Quantity)
    Ответ написан
    Комментировать
  • Как написать SQL запрос?

    LaRN
    @LaRN
    Senior Developer
    Можно так попробовать.
    Я тут учитывал кейсы, когда время выхода больше времени входа.

    SELECT userGUID, areaGUID, timeHappened AS times
      FROM users in_u
      LEFT JOIN users out_u
             ON out_u.userGUID     = in_u.userGUID
            AND out_u.areaGUID     = in_u.areaGUID
            AND out_u.inOut        = 2
            AND out_u.timeHappened > in_u.timeHappened
     WHERE in_u.inOut  = 1
       AND out_u.inOut IS NULL
    ORDER BY userGUID, areaGUID
    Ответ написан
    Комментировать
  • Чем заменить конструкцию WHERE id>count(id)?

    LaRN
    @LaRN
    Senior Developer
    Можно расчет count(id) вынести в подзапрос, тогда первый вариант должен сработать.
    https://dev.mysql.com/doc/refman/8.0/en/subqueries.html

    Если в коде, то как-то так:
    SELECT * 
      FROM table 
    WHERE id>(SELECT max(id) 
                         FROM table 
                       WHERE date < CURDATE()) 
       LIMIT 10
    Ответ написан
  • Как сформировать запрос из 2 таблиц с группировкой и SUM?

    LaRN
    @LaRN
    Senior Developer
    Можно так попробовать:
    select datatime,
           sum(case when card = 1 then amount else 0 end) as 'Cards1',
           sum(case when card = 2 then amount else 0 end) as 'Cards2',
           sum(case when card = 3 then amount else 0 end) as 'Cards3'
      from service
     group by datatime


    Но тут количество колонок задается в запросе жестко, в вашем примере их 3.
    Если оно плавающее в зависимости от записей в БД, то тут нужно динамически запрос формировать.
    Ответ написан
    3 комментария
  • Как выбрать и приоритизировать координаты на карте по другим?

    LaRN
    @LaRN
    Senior Developer
    При такого вида запросах точного попадания в координаты организации не будет и нужно определиться с размером области вокруг координат пользователя и ее формой (квадрат, прямоугольник, круг, что-то еще).
    Размер области ограничит список отбираемых организаций.
    Задать размер можно например так, пусть нужно показать все вокруг пользователя в радиусе 2 км.
    И пусть область для простоты - это квадрат.
    Из вики можно найти, что средняя длинна одного градуса широты/долготы примерно 111 км.
    Тогда вариация по широте/долготе от текущей позиции пользователя будет плюс/минус 2/111 градуса = 0,018 градуса.

    А дальше можно вот таким запросом вывести список подходящих организаций:
    SELECT us.id,
           lc.name,
           lc.address 
      FROM tb_user us
      JOIN tb_location lc
        ON lc.lat BETWEEN us.lat - 0.018 AND us.lat + 0.018
       AND lc.lon BETWEEN us.lon - 0.018 AND us.lon + 0.018


    Чтобы это нормально работало нужны индексы по полям lat, lon таблицы tb_location.
    Также лучше ограничить точность координат lat, lon например можно указать место организации с точностью до 10 метров, тогда координаты можно округлить до 0,01/111 = 9*10^-6, т.е. до 5 знаков после запятой.

    Можно еще для операции поиска координаты привести к целым числам, т.е. хранить для поиска lat/lon умноженными на 10^5 и без дробной части. При такой схеме нужно 3+5 = 8 значащих цифр и тип int подойдет для хранения. Этот вариант позволить уменьшит размер индекса по полям lat/lon, а это должно ускорить поиск.
    При таком вариант в запросе вместо
    us.lat - 0.018 AND us.lat + 0.018
    нужно указать
    us.lat - 1800 AND us.lat + 1800

    При использовании в поиске условия вида
    us.lat - 1800 AND us.lat + 1800
    есть нюанс, если искать в районе 0/360 градуса нужно делить условие на две части, вот пример когда
    us.lat - 1800 получается меньше нуля.

    BETWEEN 36000000 + (us.lat - 1800) AND 36000000
    OR
    BETWEEN 0 AND us.lat + 1800

    Если us.lat + 1800 получается больше 36000000, то аналогично две части:
    BETWEEN us.lat - 1800 AND 36000000
    OR
    BETWEEN 0 AND (us.lat + 1800)-36000000
    Ответ написан
    Комментировать
  • Как сделать запрос в БД или обработать на php для объединения часов одного дня?

    LaRN
    @LaRN
    Senior Developer
    Можно вот так попробовать.

    Я убрал из select дублирующиеся поля users.`users_id` и user_dolg.`user_id`

    Так как по полю user_dolg.`date` происходит отбор, но оно не включено в список агрегирующих полей, нужно к
    нему применить агрегирующую функцию, например так MAX(user_dolg.`date`) либо добавить поле в список агрегирующих полей.

    Так как вы присоединяете таблицу `users` левым джойном, то в случае отсутствия в ней записи по users_id в поля этой таблицы вернется значение NULL нужно бы обработать этот случай используя функцию ISNULL например или IFNULL. Если же в таблице `users` всегда есть запись для users_id из таблицы user_dolg, то лучше бы LEFT OUTER JOIN заменить на INNER JOIN. Я в запросе написал вариант с INNER JOIN.

    SELECT DISTINCT 
           users.`users_id`,
           users.`name`,
           user_dolg.`date`,
           SUM(user_dolg.hours)  AS sub_hours
      FROM `user_dolg` 
     INNER JOIN `users`
        ON users.`users_id` = user_dolg.`user_id`
     WHERE user_dolg.`date` BETWEEN  '" . $starttime . "' AND '" . $endtime . "'
     GROUP BY users.`users_id`, users.`name`, user_dolg.`date`
    HAVING COUNT(1) > 1
    Ответ написан
    6 комментариев
  • Как удалить строки из нескольких таблиц в mysql через JOIN?

    LaRN
    @LaRN
    Senior Developer
    Попробуйте так:
    DELETE users, employee, person
      FROM users 
     INNER JOIN employee 
        ON employee.user_id = users.id 
     INNER JOIN person
        ON person.user_id = employee.user_id
    Ответ написан
    Комментировать
  • Как проверить существование строки до ее отправки в форму?

    LaRN
    @LaRN
    Senior Developer
    У вас функция check возвращает true если имя пользователя есть и 'Character not found' если нет.
    Может имеет смысл всегда возвращать результат одного типа в обоих случаях (например всегда boolean) и в случае ошибки возвращать false?
    Ответ написан
    Комментировать
  • Как по таблице действий со счетом, посчитать итоговое значение?

    LaRN
    @LaRN
    Senior Developer
    Судя по описанию задачи как-то так:
    select isnull((select sum(Amount) from logs where receive_id = @userid), 0) - isnull((select sum(Amount) from logs where sender_id = @userid), 0)


    Тут @userid идентификатор пользователя для которого нужно посчитать баланс.
    Ответ написан
    1 комментарий
  • Как использовать order by и group by одновременно?

    LaRN
    @LaRN
    Senior Developer
    У вас задана группировка но в секции select нет агрегирующих функций.
    Если последнее id = Максимальное id, то можно вот такой селект написать:
    Select user_id, max(id)
    Дальше все как у вас, только order by не нужно теперь.
    Ответ написан
  • MySQL. Как удалить ограниченное количество строк из таблицы?

    LaRN
    @LaRN
    Senior Developer
    Если верить описанию вот тут:
    https://dev.mysql.com/doc/refman/8.0/en/delete.html

    То можно вот так:
    DELETE FROM b_iblock_section WHERE IBLOCK_ID=4 LIMIT 100;

    можно даже в ORDER BY задать порядок следования записей, чтобы указать в каком порядке грохнуть 100 записей.
    Ответ написан
    Комментировать
  • Как сравнить 2 списка?

    LaRN
    @LaRN
    Senior Developer
    Как-то так:
    select t1.fio
      from таблица 1 as t1
      left join таблица 2 as t2
             on t2.id = t1.id
     where t2.fio is null
    Ответ написан
    Комментировать
  • Как добавить под категорию в базу данных Sql?

    LaRN
    @LaRN
    Senior Developer
    Можно добавить в таблицу tbl_category ещё одно поле - parent_id, которое будет ссылаться на поле Category_ID этой же таблицы. Так можно будет хранить дерево категорий в одной таблице и если потребуется добавить ещё уровень вложенности то больших доработок не потребуется.
    Кроме этого, для удобства отбора, можно добавить поле IsFinal и устанавливать его в 1 для категорий, которые находятся в самом низу дерева (по сути листья).
    Ответ написан
    Комментировать
  • Как организовать хранение и быструю выборку двух полей из БД?

    LaRN
    @LaRN
    Senior Developer
    Если в будущем захотите расширить набор атрибутов, то в случае отдельной таблицы с атрибутами это будет проще сделать. Опять же для поиска по цвету / размеру любому другому атрибуту запросы будут одинаковыми, не придется переписывать "движок" магазина для каждого нового параметра.

    Ну и с точки зрения экономии диска: может оказаться, что на одном товаре будет один набор атрибуты, а на другом другой, но в БД (в случае если их добавить в таблицу с товарами) все равно они будут занимать место (хоть там и будут условно нули)
    Ответ написан
    Комментировать
  • Как выбрать данные без повторений?

    LaRN
    @LaRN
    Senior Developer
    Попробуйте так:

    SELECT 
          sign(coalesce(location_id, 0)) + sign(coalesce(division_id, -1)) + sign(coalesce(position_id, -2)) as score, title
      FROM 
          keyword 
     WHERE 
          city_id = $cityId AND 
          (division_id = $divisionId OR division_id IS NULL) AND 
          (position_id = $positionId OR division_id IS NULL) AND 
          (location_id = $locationId OR location_id IS NULL) AND
          MATCH (keyword) AGAINST ('$keys') 
    GROUP BY 
          title 
    ORDER BY 
          score 
    DESC LIMIT 10
    Ответ написан
    Комментировать
  • Какая альтернатива NOT IN в MySQL?

    LaRN
    @LaRN
    Senior Developer
    Можно использовать not exists нужно только немного изменить запрос.
    https://dev.mysql.com/doc/refman/5.7/en/exists-and...
    Ответ написан
    Комментировать
  • Как оптимизировать подобный sql?

    LaRN
    @LaRN
    Senior Developer
    Если проблема точно в этом запросе, можно попробовать разделить запрос на две части без использования
    инструкции ON DUPLICATE KEY UPDATE:

    if exists(select 1
                 from chat_lastread
                where `user_id`   = #user_id
                  and `dialog_id` =  #dialog_id)
     begin
       update chat_lastread
          set `date` = NOW()
         from chat_lastread
        where `user_id`   = #user_id
          and `dialog_id` =  #dialog_id
     end
     else
     begin
       INSERT INTO chat_lastread (
         `user_id`,
         `dialog_id`,
         `date`
       ) VALUES(
         #user_id,
         #dialog_id,
         NOW()
       )
     end
    Ответ написан
    1 комментарий
  • Что не так с полями БД?

    LaRN
    @LaRN
    Senior Developer
    В ошибке явно указано, что есть неизвестное поле:
    Unknown column 'this_.nationality' in 'field list'

    Проверьте что в таблице student есть поле nationality.
    Ответ написан
    3 комментария
  • Как сгруппировать диалоги по двум полям в MySQL через GroupBY?

    LaRN
    @LaRN
    Senior Developer
    Можно вот так попробовать:

    select dd.tovar_id, dd.sender_id
      from dialogs dd
     where not exists(select 1
                        from dialogs ds
                       where ds.tovar_id     = dd.tovar_id
                         and ds.recipient_id = dd.dd.sender_id
                         and ds.id           < dd.id)
     group by dd.tovar_id, dd.sender_id


    Тут будут все диалоги по всем товарам.
    Если нужно фильтровать по пользователю или товару, можно это сделать задав секцию where
    Ответ написан
    Комментировать