Не могу осилить NOT IN, уже бубен стер :)

eno

Новичок
Здравствуйте,

Застрял в реализации такой задачи:
Есть магазин, каждый товар имеет характеристику, в какие страны он не доставляется.
Юзер заходит, geoip определает его страну. Нужно выдать ему только те товары, которые доставляются в его страну.

Пример: юзер из Украины. Определили страну - UA, записали в переменную $country. В таблице товаров есть столбец noshipcountry, где коды стран содержаться через запятую.
Товар: водка, noshipcountries = 'UA,KZ,PL'
Товар: сало, noshipcountries = 'RU,AZ,GE'

Пробовал:
SELECT id, iname, noshipcountries, price, discount FROM shop_goods WHERE '$country' NOT IN (noshipcountries) ORDER BY id DESC;

Не срабатывает. Ну не загонять же еще раз SELECT noshipcountries FROM ... в NOT IN.
Очень не хочу делать проверку результата (т.е. прогонять все товары, а их немеренно) в php. Хочется уже из базы забрать готовую таблицу товаров, где в столбце noshipcountries не присутсвует UA.
 

Ярослав

Новичок
eno
Должно быть 'UA','KZ','PL' а не 'UA,KZ,PL'

PHP:
$noshipcountries = "'" . join("','", explode($noshipcountries, ',')) . "'"
 

akd

dive now, work later
Команда форума
eno, на самом деле нормальный вариант у тебя всего один - переделать структуру базы в нормальную. Ярослав тебе предлагает такое-же уг, которое у тебя уже есть.
 

eno

Новичок
akd, ты под нормальным что имеешь вииду? загонять каждую страну в свою колонку? Дело в том, что я пока что еще не знаю какие будут страны. Руководство там само решает что куда. Единственное, что мне было бы удобнее, если бы были не запреты на страны, а указывалось бы в какие страны доставляют, но начальник упрямо хочет ставить именно запреты.
 

Духовность™

Продвинутый новичок
в реляционных СУБД хранить что-либо через запятую - это адъ и погибель. так нельзя. или юзайте set
 

akd

dive now, work later
Команда форума
eno я имею ввиду нормальные формы.
список запретов или список разрешенных стран, в данном случае, абсолютно пофег.

как бы делал я.
1. таблица стран
2. таблица груп недоставки (доставки, если по твоему) ... групп бесконечное множество, товар всегда в одной группе.
3. таблица товаров со ID группы
4. таблица связей ID группы - ID страны (многие к многим)

дальше уже банально все
 

eno

Новичок
Понимаю мысль, иметь один числовой id для комбинации стран - это, конечно, удобно. Но... мне нужно создавать id для всех возможных комбинаций стран. А при добавлении новых стран, создавать еще комбинации. И чем больше будет стран, тем в геометрической прогрессии больше будет комбинаций.
А никакого другого пути ты не видишь для решения это задачи?
 

Royal Flash

-=MaestrO=-
Создай отдельную таблицу, в которой будут храниться все страны, в которые товар доставляется:

id_tovar id_strana
12341 5
12341 7
12341 9
1 5
1 3

Хранить данные через запятую, это уж точно не вариант...
 

whirlwind

TDD infected, paranoid
PHP:
mysql> select * from item;
+----+---------------------+
| id | name                |
+----+---------------------+
|  1 | megabundle          |
|  2 | suppa-duppa product |
+----+---------------------+
2 rows in set (0.00 sec)

mysql> select * from country;
+----+------+
| id | code |
+----+------+
|  1 | UA   |
|  2 | KZ   |
+----+------+
2 rows in set (0.00 sec)

mysql> select * from restricted_item_country;
+----+------+---------+
| id | item | country |
+----+------+---------+
|  1 |    1 |       2 |
|  2 |    2 |       1 |
+----+------+---------+
2 rows in set (0.00 sec)

mysql> select i.name as item_name,r.id from item as i left join restricted_item_country as r on (i.id=r.item and r.country=2) where r.id IS NULL;
+---------------------+------+
| item_name           | id   |
+---------------------+------+
| suppa-duppa product | NULL |
+---------------------+------+
1 row in set (0.04 sec)

mysql> select i.name as item_name,r.id from item as i left join restricted_item_country as r on (i.id=r.item and r.country=1) where r.id IS NULL;
+------------+------+
| item_name  | id   |
+------------+------+
| megabundle | NULL |
+------------+------+
1 row in set (0.00 sec)
 

akd

dive now, work later
Команда форума
eno, не понимаешь. по дефолту, все товары можно отправлять во все страны, исключения привязываются к группам, группы к товару. все. в данном случае твой начальник прав.
whirlwind, группы я туда вкрутил, чтобы проще было управлять пачками стран типа евросоюза, снг и прочими образованиями.
 

eno

Новичок
whirlwind, akd, понял логику. Спасибо!
Т.е. в отдельной таблице хранить все товары с привязкой их к странам. Если к 1 товару закреплены 3 страны, то по номеру этого товара будет 3 строки в этой таблице. Так и сделаю. Еще раз спасибо!
 

radioheaded

PHP нуб
PHP:
WHERE CONCAT(',', noshipcountries, ',') LIKE '%,$country,%'
Да, я знаю толк в извращениях. Это решение для указанной структуры, но при этом должно быть понятно, что это очень медленный запрос и ни один индекс работать здесь не будет. Поэтому да, структуру нужно переделывать.
 
Сверху