Как да търся в поле структорирано като масив

Hous

Registered
Имам следните примерни записи:
Код:
id|myfield
1|3
2|3,4,5
3|5,4,3
4|7
5|9

Давам на потребителя възможността да избира с чекбокс няколко от стойностите и после искам mysql да ги сравни с тези които са в примерното поле myfield.
Например , ако потребителя зададе стойност:
1= празен резултат
3=полет с id 1,2,3
7=поле с id 4
(не избира нищо)=всички полета
3;4=полета с id 2,3
 
С функцията (на mysql) FIND_IN_SET(?, myfield) - заместваш питанката с това, което търсиш...
 
Мъчих се вече 30 мин, със IN или find_in_set
но IN не може да търси при няколко стойности (1,2,3), или поне аз не успях
Код:
myfield IN ('5')
връща id : 2,3 но ако му дам повече от една стойнст IN просто връща презен резултат:
Код:
myfield IN('3','4')

а при find_in_set мога да подам само 1 стойност за сравнение с останалите, т.е. когато задам

Код:
find_in_set('5','1,5,3')
го намира , но ако задам
Код:
find_in_set('1,5','1,5,3')
връща празен резултат.
 
По-добре е полетата ти да имат сингулярни значения. Мисълта ми е вместо
Код:
id|myfield 
1|3 
2|3,4,5 
3|5,4,3 
4|7 
5|9
да имаш
Код:
id|myfield 
1|3 
2|3
2|4
2|5 
3|5
3|4
3|3 
4|7 
5|9
с индекс на myfield заявката ще е доста по-бърза:
[sql]SELECT id WHERE myfield=7
SELECT DISTINCT id WHERE myfield IN (3,4)[/sql]
 
Ако съм разбрал правилно питането това е заченката на идеята, която търсиш:

[sql]SELECT * FROM `beta` WHERE INSTR(`myfield`, '3') > 0[/sql]

Като замениш, разбира се, 3 със стойността на потребителя!
 
@raiden да би било, но вече всичко е записано , примерни полета са само за да покажа идеята, няма как да си играя с базата.

@g9m29 ами... разбирам горе долу идеята, но пак казвам аз имам понякога сравняване на много стойности (2-3-4) със стойности записани като масив, а понякога потребителя може да не подаде никакви стойности...
 
Имам една идея, но е малко хамалска ..
Защо не използваш нещо по-елементарно .. като LIKE. Извади тези данни с php-то и сглоби заявката.

Пример:
PHP:
$get = mysql_query("SELECT `myfield` FROM `table` WHERE `id`=2 ")
$r = mysql_fetch_assoc($get);

   $ex = explode(",", $r['myfield']);
   for ($i=0; $i < count($ex); $i++) { 
		 $where .=  ' `myfield` LIKE "%'.$ex[$i].'%" OR ';
   }
   $where = substr($where,0,-3);

$sql = 'SELECT * FROM `table` WHERE '.$where; // готова заявка ?

Знам, че ще е много зле от към бързина ама просто идея - ако ти светне нещо и успееш да я развиеш, така че да ти върши работа ще е супер ;) :?: :idea:
 
благодаря за идеята, но и аз намерих няколко по "груби" метода


Код:
$izbor="1,2,3,4,5,6,7,8,9";//masiv
$num=array_count_values($izbor);
if($num=1){$q="find_in_set('3',myfield)";}
else if($num=2){$q="find_in_set('3',myfield) or find_in_set('4',myfield)";}
else if($num=3){$q="find_in_set('3',myfield) or find_in_set('4',myfield) or find_in_set('5',myfield))";}
//i taka oshte 7 stoinosti, tai kato potrebitelq ima maksimum 10 vazmojni izbora)



, идеята ми е да е нещо оптимално (поне що годе) и да е максимално просто.
Ще изчакам за още идеи. :)
 
Ако ще гледаме бързината то тогава php-то е в пъти по-бързо от sql-а. Тъй че това би ти свършило перфектна работа според мен:

PHP:
$q = mysql_query("SELECT * FROM `beta`");
$idMatches = array();
$userInput = "3,5,4";
while ($r = mysql_fetch_array($q, MYSQL_NUM)){
		$values = explode(",", $r[1]);
		$userInputs = explode(",", $userInput);
		((array_diff($userInputs, $values) == NULL) ? $idMatches[] = $r[0] : "" );
}

Като си замениш съответно заявката с твоя PDO и $userInput го направиш да е $_POST. Аз съм сложил "3,5,4" за да има нещо. Това с explode може да се съчетае за да няма if else във while, но го правя с цел, ако има само 1 цифра изобщо да не се влиза в else, за да се увеличи бързодействието.

П.С Съкратих кода с 5 реда!!!

П.С2 Съкратих кода с 3 реда!!!

П.С3 $idMatches = array(); съдържа идентификаторите от датабазата на всички полета съдържащи стойностите !!!
 
Направо се изходихте върху теорията за релационните бази данни. Не е правилно, не е било правилно и никога няма да бъде правилно стойност в поле да бъде резултат от конкатенация.

@Hous - оправи си базата данни, повярвай ми по-добрият вариант е - да ще си играеш с нея, ще трябва да промениш и php кода, който борави с данните, но веднъж. После ще имаш правилно проектирана таблица и заявките ти ще се изпълняват за милисекунди вместо при всяка заявка да тормозиш

Като за начало си направи копие на таблицата, но с първичния ключ на 2 полета id и myfield, след това по желание (за по-бързи заявки при много записи) можеш да добавиш и index на myfield. После процедурата може да се извърши много лесно с PHP:
table1 - сегашната таблица
table2 - новата таблица
и правиш нещо такова
PHP:
$query = mysql_query("SELECT * FROM `table1`");
while($row=mysql_fetch_assoc($query)) {
$values = array();
foreach(explode(",",$row['myfield']) as $v) {
$values[] ="('".$row['id']."','$v')";
}
mysql_query("INSERT INTO `table2` VALUES(".implode(",",$values).")");
}
с което си решаваш проблема веднъж за винаги

ПС: ако в таблицата table1 имаш и други колони освен id и myfield, то в таблицата table2 трябва да имаш само id и myfield, a myfield от table1 го махаш. Така table2 ще ти играе ролята на свързваща и ще реализира връзката много към много. Ако нещо не ти е ясно ще ти обясня
 
За последния коментар. Просто ми се отщя да пиша каквото и да било като разбрах, че се иска матчване много към много - индикация за грозно омазан дизайн на базата.
 
Съжалявам за коментара, който може да прозвучи малко грубо, но по горе момчето каза, че не може да си играе с датабазата. За това, да ви пикам на теориите за релациите и на кодовете не по темата!
 
Ами в крайна сметка реших да оставя нещата, отказах се от "поръчката". Таблицата не е моя и нямам достъп до структурата. Благодаря на всички за мненията. :)
 
@lamerko не връзката М-М, а начина по който е реализирана е грешката в дизайна
@g9m29 би трябвало да знаеш, че релация много към много не съществува - тя се реализира чрез две отделни релации 1 към много и трета таблица, която да ги свърже. Това се опитвам да обясня на автора, като предлагам и решение

:o
 

Back
Горе