2010-07-31 3 views
4

Question1:MySQL (взрываются/соответствие массив)

MySQL таблица

идентификатор | массив
1 | 1,2,3
2 | 2
3 | 2,3
4 | 4,5,6

$_GET['id'] = 2; 
$a = mysql_query("SELECT * FROM `table` WHERE `array` ??? '$_GET[id]'"); 

На этом этапе я хочу запустить через весь массив и посмотреть, если он совпадает с $ _GET [ «ID»], поэтому он должен выводить:

идентификаторами: 1,2,3

question2:

MySQL таблица

ID | массив
1 | 4,5,6
2 | 3,4,7

$_GET['id'] = 4; 
$a = mysql_query("SELECT * FROM `table` WHERE `array` ??? '$_GET[id]'"); 

На этом этапе я только хочу, чтобы соответствовать против первого элемента в массиве, поэтому он должен выводить:

ID: 4

я могу только подумайте об использовании PHP для этого, но я предпочел бы сделать все, что только в запросе MySQL, если это возможно.

$a = mysql_query("SELECT * FROM `table`"); 
while($b = mysql_fetch_assoc($a)) 
{ 
    $elements = explode(',', $b['array']); 
    foreach($elements as $element) 
    { 
     if($element == $_GET['id']) 
     { 
      echo $b['id'].'<br />'; 
     } 
    } 
} 

или

$a = mysql_query("SELECT * FROM `table`"); 
while($b = mysql_fetch_assoc($a)) 
{ 
    $array = $b['array']; 

    if(in_array($_GET['id'], $array)) 
    { 
     echo $b['id'].'<br />'; 
    } 
} 

, что будет выглядеть просто ужасно.

+0

нормализовать дб схему – knittl

ответ

1

Ваша структура данных в БД не является оптимальной для запроса того, как вы хотите.

Для первого вопроса:

mysql_query("SELECT * FROM table WHERE array LIKE '%,$_GET[id],%' OR array LIKE '$_GET[id],%' OR array LIKE '%,$_GET[id]' OR array = '$_GET[id]'"); 

Для второго:

mysql_query("SELECT id, SUBSTR(array, 1, POSITION(',' IN array) - 1) AS array FROM table WHERE array LIKE '$_GET[id],%' OR array = '$_GET[id]'"); 

Как вы можете видеть, эти запросы не очень, но они будут делать то, что вы хотите.

+0

Что касается в первом вопросе, когда значение находится в начале строки? Оно не будет соответствовать (не имеет перед ним). Также не забывайте * дезинфицировать свой вход * !! –

+0

эй, спасибо, почему, как еще вы его структурируете? Я просто подумал, что было бы легче сохранить массив для определенных задач. – 2010-07-31 08:04:38

+2

@Blair: запрос соответствует if число начинается с массива или является единственным элементом в массиве. @ user317005: Вы должны сохранить каждое значение массива как отдельную строку, например 'create table table_name (id int, value int)' каждый идентификатор будет иметь несколько строк, но гораздо проще делать запросы. – jmz

0

непроверенная, но вы должны быть в состоянии использовать:

Вопрос 1:

SELECT * FROM table WHERE array REGEXP '(^|,)?(,|$)'; 
// Match either the start of the string, or a , then the query value, then either a , or the end of the string 

Вопрос 2:

SELECT * FROM table WHERE array REGEXP '^?(,|$)'; 
// Match the start of the string, then the query value, then either a , or the end of the string 

Где ? заменяется с $_GET значением. Понятия не имею.

0

Первый:

SELECT * FROM table WHERE array LIKE '$_GET[id],%' OR array LIKE '%,$_GET[id],%' OR array LIKE '%,$_GET[id]' OR array = '$_GET[id] 

Второй:

SELECT * FROM table WHERE array LIKE '$_GET[id],%' OR array = '$_GET[id] 

Объяснение:

  • '$_GET[id],%' будет соответствовать, если массив начать с $_GET[id]
  • '%,$_GET[id],%' будет соответствовать, если $_GET[id] между любыми двумя из элементов массива
  • '%,$_GET[id]' будет соответствовать, если массив конец с $_GET[id]
  • массив = '$_GET[id]' матч, если массив содержит только один элемент, равный $_GET[id]
+0

'23, 4 'LIKE' 3 '. не совсем правильно – knittl

+0

'23, 4 'LIKE' 3 ', это неправда. '3,4', как '3', это правда. – Sadat

+0

um да. извините, вы были правы. моя ошибка – knittl

4

О том, что вы можете/должны структурировать свою базу данных по-разному, уже упоминалось (см. http://en.wikipedia.org/wiki/Database_normalization). Но ....

См FIND_IN_SET()

MySQL> SELECT FIND_IN_SET ('б', 'а, Ь, с, d');
-> 2

e.g.

<?php 
$mysql = init();  
bar($mysql, 1); 
bar($mysql, 2); 
bar($mysql, 3); 
bar($mysql, 4); 


function bar($mysql, $x) { 
    $sql_x = mysql_real_escape_string($x, $mysql); 
    $result = mysql_query("SELECT id, foo FROM soTest WHERE FIND_IN_SET('$sql_x', foo)", $mysql) or die(mysql_error()); 

    echo "$x:\n"; 
    while(false!==($row=mysql_fetch_array($result, MYSQL_ASSOC))) { 
    echo $row['id'], ' ', $row['foo'], "\n"; 
    } 
    echo "----\n"; 
} 

function init() { 
    $mysql = mysql_connect('localhost', 'localonly', 'localonly') or die(mysql_error()); 
    mysql_select_db('test', $mysql) or die(mysql_error()); 
    mysql_query('CREATE TEMPORARY TABLE soTest (id int auto_increment, foo varchar(64), primary key(id))', $mysql) or die(__LINE__.' '.mysql_error()); 
    mysql_query("INSERT INTO soTest (foo) VALUES ('1,2,3'), ('2,4'), ('3'), ('2,3'), ('1,2')", $mysql) or die(__LINE__.' '.mysql_error()); 
    return $mysql; 
} 

печатает

1: 
1 1,2,3 
5 1,2 
---- 
2: 
1 1,2,3 
2 2,4 
4 2,3 
5 1,2 
---- 
3: 
1 1,2,3 
3 3 
4 2,3 
---- 
4: 
2 2,4 
---- 

MySQL не может использовать индексы для выполнения этого поиска, то есть результаты запроса в полном сканировании таблицы, см Optimizing Queries with EXPLAIN


редактирование:
Для ваш второй вопрос, вам нужно только изменить предложение WHERE на
WHERE FIND_IN_SET('$sql_x', foo)=1

0

Я бы рекомендовал вам привести вашу базу данных в first normal form, e. г.

CREATE TABLE t_master (
    id INT PRIMARY KEY AUTO_INCREMENT 
); 

CREATE TABLE t_array (
    id INT PRIMARY KEY AUTO_INCREMENT, 
    master_id INT NOT NULL, 
    value INT, 
    CONSTRAINT fk_array_master_id FOREIGN KEY (master_id) REFERENCES t_master (id) 
); 

Затем вы можете найти записи в t_master, которые имеют специфический value с

$q = 'SELECT m.* ' . 
    'FROM t_master AS m INNER JOIN t_array AS a ON a.master_id = m.id ' . 
    "WHERE a.value = '" . mysql_real_escape_string($_GET['id'], $db) . "' " . 
    'GROUP BY m.id'; 

Самое главное преимущество заключается в том, что если у вас есть много значений, вы можете добавить индекс, чтобы найти их много быстрее:

ALTER TABLE t_array ADD INDEX idx_value (value); 

Менее очевидным, но не последним преимуществом является то, что ваши запросы становятся более логичными и структурированными.

0

Если вы не можете нормализовать схему (это лучший вариант:

SELECT * 
    FROM table 
WHERE ','+array+',' LIKE '%,$_GET[id],%' 

Но если вам нужно получить доступ к записям по идентификатору, то вы действительно должны нормализовать