За последние 24 часа нас посетили 22959 программистов и 1230 роботов. Сейчас ищут 723 программиста ...

Выборка из нескольких таблиц с вычислением разницы

Тема в разделе "MySQL", создана пользователем karmay, 14 авг 2018.

  1. karmay

    karmay Активный пользователь

    С нами с:
    9 ноя 2017
    Сообщения:
    180
    Симпатии:
    18
    Адрес:
    Н.Новгород
    Всем привет, уже долго не могу решить проблему, нужна помощь.
    Есть 3 таблицы, запчасти, место на складе, и таблица соотношения запчасти->место
    таблица локаций простая, id места и его название
    1.png
    это таблица с запчастями

    2.png
    это таблица соотношений.
    Суть в том, что на складе общее количество фильтров MANN 6, из этих 6 штук 2 лежат в коробке №2 и 2 лежат в коробке №8.
    Внимание вопрос: как составить запрос sql который будет показывать на странице только те запчасти, которые не соответствуют ни одной коробке??? Т.е. сейчас мне надо показать те 2 фильтра, которые только что приехали и их необходимо распределить по коробкам.
     
  2. karmay

    karmay Активный пользователь

    С нами с:
    9 ноя 2017
    Сообщения:
    180
    Симпатии:
    18
    Адрес:
    Н.Новгород
    Часть вопроса я все таки решил
    PHP:
    1. $sql = "SELECT DISTINCT parts.id, parts.manufacturer, parts.vendor, parts.name,
    2.                parts.count-(SELECT SUM(parts_location.count) FROM `parts_location` WHERE parts_location.parts_id=parts.id) AS count,
    3.                parts.price, parts.description
    4.                FROM `parts`
    5.                LEFT JOIN `parts_location` ON parts.id=parts_location.parts_id
    6.                ";
    Но теперь если в таблице запчастей присутствует запись, которой нет в таблице соотношений, то вложенный запрос возвращает NULL и в итоге в count записывается NULL, как быть?
    PHP:
    1. array (size=7)
    2.       'id' => string '2' (length=1)
    3.       'manufacturer' => string 'SAKURA' (length=6)
    4.       'vendor' => string 'C1110' (length=5)
    5.       'name' => string 'ФИЛЬТР МАСЛЯНЫЙ' (length=29)
    6.       'count' => null
    7.       'price' => string '250' (length=3)
    8.       'description' => string '' (length=0)
     
  3. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    скорее всего вложенный запрос надо поместить в конструкцию IF
    хотя я лично бы сделал немного по другому и вложенный запрос с группировкой применил во FROM взамест `parts_location`
    --- Добавлено ---
    типа получается parts.count-NULL = NULL ?
     
    karmay нравится это.
  4. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    select field ... и даёт такой результат, что field2 - field = жопа

    нужно просто либо при выборке
    select if (field = null, 0, field)

    либо при операции
    field2 - if (field = null, 0, field)

    как вариант отказаться от null, нафик оно в числовом столбике
     
  5. karmay

    karmay Активный пользователь

    С нами с:
    9 ноя 2017
    Сообщения:
    180
    Симпатии:
    18
    Адрес:
    Н.Новгород
    В таблице нет NULL, там только числа, я так понимаю, это от того, что подзапрос возвращает NULL, т.к. нет записи с parts_id = 2

    ну да, подзапрос вернул NULL, а арифметические операции с ним в результате дают NULL.

    Можно подробнее, про вложенный запрос в FROM?
     
  6. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    NULL возвращает результат подзапроса, от него нельзя отказаться))
    --- Добавлено ---
    можно, для начала напишите запрос для `parts_location` с группировкой по parts_id
     
  7. villiwalla

    villiwalla Активный пользователь

    С нами с:
    14 дек 2016
    Сообщения:
    471
    Симпатии:
    70
    А нельзя что-то типа ...location_id not in(); ?
     
  8. karmay

    karmay Активный пользователь

    С нами с:
    9 ноя 2017
    Сообщения:
    180
    Симпатии:
    18
    Адрес:
    Н.Новгород
    Так я и не понял, что господа знатоки имеют ввиду, вопрос решен с помощью IFNULL, @Valick спасибо.
    PHP:
    1. $sql = "SELECT DISTINCT parts.id, parts.manufacturer, parts.vendor, parts.name,
    2.         parts.count-( IFNULL( (SELECT SUM(parts_location.count) FROM `parts_location` WHERE parts_location.parts_id=parts.id), 0) ) AS count,
    3.         parts.price, parts.description
    4.         FROM `parts`
    5.         LEFT JOIN `parts_location` ON parts.id=parts_location.parts_id
    6.         ";
     
    Valick нравится это.
  9. keren

    keren Новичок

    С нами с:
    15 ноя 2017
    Сообщения:
    513
    Симпатии:
    42
    Так это возвращает лишь дефолтное значение в случае null, так что думаю надо решать вопрос с
    Код (Text):
    1. (SELECT SUM(parts_location.count) FROM `parts_location` WHERE parts_location.parts_id=parts.id)
     
  10. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    а если очень хорошо подумать? ну или хотя бы внимательно прочитать тему?
     
  11. keren

    keren Новичок

    С нами с:
    15 ноя 2017
    Сообщения:
    513
    Симпатии:
    42
    @Valick, если не понял что я написал это не повод менять цитату, там дефолт после запятой.
     
  12. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    @keren, неудачная цитата, которую я не могу поправить (религия форума не позволяет) ни коим образом не влияет на мой вам ответ
     
  13. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.591
    Симпатии:
    360
    То есть, не свободное количество оставшееся без коробок (в данном примере 2 = 6 - 2 - 2), а только те, что вообще без коробок?
    --- Добавлено ---
    И приложите уж набор тестовых данных и скрипты для создания табличек :)
     
  14. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    А как отличить тех кто без коробок от тех которые вообще без коробок?
    Зойчем? ТС с минимум подсказок со стороны сообщества справился с задачей, да и в первом сообщении таблицы картинками всё яснопонятно. Так шо он дважды молодец.
     
  15. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.591
    Симпатии:
    360
    Да, вижу, что нужен количественный остаток, а не те, что вообще без коробок :)
    Можно ведь использовать группировку... тогда и без вложенного запроса на количество "в коробках" можно обойтись.
     
  16. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    там тоже на тоже, я предлагал тс не захотел
     
  17. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.591
    Симпатии:
    360
    @karmay, сравните с вариантом:
    Код (Text):
    1. select p.`name`, p.`count` as cnt, p.count - sum(ifnull(pl.`count`,0)) as remainder
    2. from parts p left join parts_location pl on pl.parts_id = p.id
    3. group by p.id
    4. having remainder > 0;
    Если нужны нулевые остатки, или, не дай провидение - отрицательные, то можно убрать выражение having.
    @Valick, а вложенный запрос в данном случае - явное излишество :)
     
    igordata нравится это.