MySQL(爆炸/匹配数组)

时间:2010-07-31 07:49:47

标签: php mysql arrays explode

问题1:

MySQL表格

id |阵列
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']匹配,因此它应输出:

ids:1,2,3

问题2:

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 />';
    }
}

看起来很糟糕。

6 个答案:

答案 0 :(得分:4)

您可以/应该以不同方式构建数据库(参见http://en.wikipedia.org/wiki/Database_normalization)。但....

请参阅FIND_IN_SET()

的MySQL&GT; SELECT FIND_IN_SET('b','a,b,c,d');
         - &GT; 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

答案 1 :(得分:2)

数据库中的数据结构不是查询所需方式的最佳选择。

对于第一个问题:

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]'");

正如您所看到的,这些查询并不漂亮,但它们可以做您想要的。

答案 2 :(得分: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值。 不知道这个的表现。

答案 3 :(得分: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]将匹配
  • array = '$_GET[id]'匹配,如果数组只包含一个等于$_GET[id]
  • 的项目

答案 4 :(得分: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);

一个不那么明显但不是最后一个优点是你的查询变得更加合乎逻辑和结构化。

答案 5 :(得分:0)

如果您无法规范化您的架构(这是最佳选择:

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

但是如果你需要通过id访问记录,那么你真的应该规范化