Обновление таблицы в бд данными, которые когда-то были, но теперь отсутствуют — как?
Здравствуйте! Есть товары, которые прилетают по API, их заношу в бд, но иногда часть товаров отсутствует в API и в бд нужно обнулить остатки. Как это сделать? Мое решение - завести новое поле типа ENUM со значениями: ('Y','N','NN') - где Y - обновлено по API, N - по умолчанию для всех товаров, NN - было когда-то обновлено, но т.к. товар этот по API не пришел ставим NN. Хотя чувствую что бред какой-то, потому что мне по сути то и не нужно доп. поле, мне всего лишь нужно у тех товаров, которые когда-то были обновлены в бд по API, но которые при следующем обновлении по API вдруг отсутствуют в этом API - просто поставить 0.
P.S. делаю запрос в бд, вытаскиваю товары которые есть в API и пытаюсь искать в массиве вытащенных товаров - товары, которых нет в API через in_array, но что-то фигня какая-то получается, находит один единственный товар, который есть и в API и в бд...
Ну во-первых, к "бизнесу" мы уже обращались (т.е. к поставщикам), они не могут, или не хотят показывать товары, у которых count = 0 и/или price = 0, они просто убирают эти товары из показа.
Во-вторых, у нас на сайте так - если кол-во товаров 0, то мы их все-равно показываем на сайте, просто статус ставим в "под заказ", поэтому и нужно какое-то решение, типа: если товар когда-то был обновлен через поставщика, но в этот раз его в списке просто нет, то поставить ему кол-во 0, при этом статус поставить в "под заказ". Цена при этом не обновляется, а остается той, которая была когда последний раз обновляли от поставщика.
mayton2019, Вот как раз NULL не лучшая идея. Это значение можно использовать как дефолтное для необязательных полей, но не для отсутствия чего-либо (где нужно использовать 0). Да еще и в цене (какой нулл в цене нафиг?).
Кроме того, это осложняет выборки, особенно с применением построителей запросов.
ThunderCat, не понимаю вообще зачем здесь построители запросов.
Есть базовой свойство реляционных систем. Иметь в кортеже пустое значение.
Будете считать SUM/AVG - заменяйте на правильное число.
не понимаю вообще зачем здесь построители запросов.
Затем что системы хранения зачастую не существуют сами по себе в вакууме, а используются прикладной частью ПО, которая по большей части пишется на фреймворках и с использованием библиотек (практически всегда используя ПЗ). Это надо учитывать в проектировании БД сразу, а не когда паленая птица клюнет в ягодицу...
mayton2019, о, да, аж в 1 шаг - данные будут использоваться во фреймворках. Ну или 2, если совсем нет понятия о прикладной части - фреймворки используют ПЗ.
1) id с API и id в бд не совпадают - это логично.
2) я составляю список артикулов полученных через API, они эквивалентны названиям товаров в бд и делаю запрос в бд, чтобы получить список обновляемых товаров, а уже потом обновляю.
Новые - не добавляю, только обновляю уже имеющиеся - кол-во и цену.
Сфига ли это логично? Если в апи вам всегда приходит товар с одинаковым айди - его следует хранить у себя как уникальный ключ, не в первичный айди, а что-то типа supler_id. Если у поставщика он уникально идентифицирует товар. Так же ключем может быть SKU, если апи его передает. Есть нюансы с артикулом, так как в артикул пишут все что можно и неможно о товаре(рост/вес/размер/цвет), а SKU уникален и неизменен в рамках системы.
список артикулов полученных через API, они эквивалентны названиям товаров в бд
Очень странная идея. Опираться в выборке на название товара, который поставщик может поменять в любой момент как минимум странно. Нашли они опечатку, поменяли название на правильное - все, у вас получилась лажа... Ключ должен быть неизменным по умолчанию, название же таковым точно не является.
Логично потому что товары не все приходят от поставщиков, представьте себе если придет id от поставщика, который есть уже в бд, но от другого товара - в этом случае тоже будет лажа..., именно поэтому кроме как на название товара опираться не на что. Да, согласен, если в названии товара произойдут изменения у поставщика, то это будет не очень хорошо, но не для бд, т.к. делаю выборку только тех товаров, имена которых совпадают в бд. В этом случае просто товар не обновится на сайте и всё, но тоже приятного мало.
представьте себе если придет id от поставщика, который есть уже в бд, но от другого товара
Еще раз - у вас есть 2 айди, ваш личный первичный ключ таблицы - id, и supler_id, который идет в апи и будет ключом для сверки с поставщиком. Вот на него и надо ориентироваться при обновлении товаров. Или, как я написал выше, можно использовать SKU, если таковой есть в ответе апи.
ThunderCat, Еще раз: не все товары обновляются через API и да, забыл уточнить еще одна немаловажная деталь - поставщиков пока три, но может быть и более, id которых могут пересекаться и совпадать, а товары при этом разные.
99-rus, Про количество поставщиков во первых - фигасе деталь, во вторых - ну заведите еще поле номер поставщика, поставщиков в отдельную справочную таблицу киньте. Будет у вас составной ключ - поставщик_айди и товар_айди. Если нет айди товара от поставщика - вот там можно нулл, хотя и 0 тоже пойдет, это не критично.
ThunderCat, Хорошо, в принципе как вариант - спасибо, буду иметь ввиду.
Но вопрос все равно остается открытым:
1. Обновляем кол-во и цену от поставщика, добавили id_товара и id_поставщика, допустим.
2. Следующее обновление - нету этого id_товара у поставщика - что делаем?
Я же сначала делаю запрос в бд на основе товаров от поставщика - вытащи мне товары с бд, где id_товаров в бд = список id_товаров от поставщика, чтобы потом обновить только эти товары.
Но что делать, если в этом списке отсутствуют те id, которые были ранее обновлены у меня в бд? Искать через in_array, array_search, или еще как? Как понять какие именно id отсутствуют чтобы у них кол-во поставить в 0?
P.S. хотя не, сейчас подумал, не вариант. Изначально id от поставщиков нету в бд и какие товары обновлять коду будет неизвестно, а заносить туда эти id чтобы потом по ним обновлять - тоже не вариант, потому что полгода, год буду заносить, пока все товары не занесутся с id, а потом они возьмут и добавят новые товары, которые будут у нас в бд, но id которых не будет от поставщика - как итог ничего не обновится :(
Изначально id от поставщиков нету в бд и какие товары обновлять коду будет неизвестно,
Понятно что архитектура кривая изначально. О чем думал проектировщик бд при создании остается загадкой, но проблема у вас здесь и сейчас.
Для начала:
1) вынесите в вопрос структуру таблицы, в идеале в виде креэйт тэйбл.
2) Список общих (одинаковых) полей приходящих с разных апи
3) Количество записей в таблице товаров
Как я вижу решение:
1) На основе существующих данных попытаться для начала разделить товары по поставщикам
2) Создать поле уникальный ключ товара на основе артикула (например хэш)
3) Так же создать айди товара поставщика, оставить нулл по дефолту и по мере обновления менять на нормальные айди от поставщика.
Получится что как только вы получаете список товаров, вы вносите все их в базу вместе с айди товара от поставщика, ориентируясь на хеш, тогда в принципе все айди в базу уже прописаны, и вышеприведенный апдейт сделает ровно то что нужно. Постепенно все данные заполнятся, и скрипт можно будет переориентировать только на айди товара.
Есть товары, которые прилетают по API, их заношу в бд, но иногда часть товаров отсутствует в API и в бд нужно обнулить остатки.
Элементарно.
То, что приходит по API, нужно не пихать сразу в рабочую таблицу, а сохранить во временную таблицу. А потом обновить рабочую таблицу, используя полученные данные как источник данных. Потребуется два запроса - первый обновит записи о товарах, имеющихся в пришедшем списке, и добавит новые (INSERT .. SELECT .. ODKU), второй поставит требуемую пометку в нужном поле (UPDATE .. FROM .. LEFT JOIN .. WHERE .. IS NULL).
Альтернативный вариант - добавить в таблицу (если не имеется, что было бы весьма странно для описываемой системы) поле штампа времени обновления записи (updated_at). Перед обновлением по данным API зафиксировать время начала процесса (получить запросом с сервера MySQL), после чего вторым запросом поставить соотв. пометку в те записи, где этот штамп времени ранее запомненного.
Не очень понятно...
Что я делаю, попробую объяснить еще раз:
1) Делаю запрос к API, получаю список артикулов, которые эквивалентны названиям товаров в бд.
2) Сохраняю список в строку ('art1', 'art2', 'art3'); etc...
3) Вытаскиваю из бд товары, которые соответствуют этой строке:
"SELECT `id`, `name`, `price`, `count` FROM `table` WHERE `name` in('art1', 'art2', 'art3')";
4) Затем обновляю в бд:
// тут цикл foreach начало
$price = floatval($item['price']['ric']);
$name = $itemName['name'];
$sqlPartName .= ($sqlPartName == '') ? "'$name'":','."'$name'";
$casePrice .= " WHEN '$name' THEN '$price'";
// тут цикл foreach конец
"UPDATE `table` set `price` = (CASE `name` $casePrice END) WHERE `name` IN ($sqlPartName)";
99-rus, бред сивой кобылы. Это ж ты состаришься, пока все записи по одной обработаются...
Хочешь пример? Выкладывай:
Данные, которые получаешь из API. Ты ж не только список артикулов получаешь, но и ещё что-то к ним привязанное, верно? Пример - 3-4 такие записи.
Структуру данных в рабочей таблице. Пример наполнения (3-5 записей, причём часть из них должна присутствовать в списке по пункту 1, а часть нет).
Подробное описание обновления. Типа "если артикул найден, то в поле ... таблицы записываем значение из ..., а в поле ... из ...". Заодно расскажи, куда ставить ноль, если записи нет, и что делать, если, наоборот, запись появилась впервые. И соответственно показать требуемое финальное состояние данных - для примера данных по пунктам 1 и 2.
Да, и, задавая вопрос по MySQL, не надо приводить код на PHP. Это всё равно, что пол-сообщения написать на китайском...