4

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

それはひどいように見えるでしょう。

4

6 に答える 6

4

データベースを別の方法で構造化できる/すべきであるということは、すでに言及されています(http://en.wikipedia.org/wiki/Database_normalizationを参照)。だが....

FIND_IN_SET()を参照してください

mysql> SELECT FIND_IN_SET('b'、'a、b、c、d');
-> 2

例えば

<?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はこの検索を実行するためにインデックスを使用できません。つまり、クエリは全表スキャンになります。EXPLAINを使用したクエリの最適化を参照してください。


編集:
2番目の質問では、WHERE句を次のように変更するだけです。
WHERE FIND_IN_SET('$sql_x', foo)=1

于 2010-07-31T08:50:47.090 に答える
2

DB内のデータ構造は、希望する方法でクエリを実行するのに最適ではありません。

最初の質問の場合:

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

2番目の場合:

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

ご覧のとおり、これらのクエリはきれいではありませんが、必要な処理を実行します。

于 2010-07-31T08:00:23.960 に答える
0

データベースを最初の正規形にすることをお勧めします。

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);

あまり明白ではありませんが、最後の利点ではありませんが、クエリがより論理的で構造化されていることです。

于 2010-07-31T09:06:04.640 に答える
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。これのパフォーマンスについてはわかりません。

于 2010-07-31T08:01:57.437 に答える
0

最初の1つ:

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]配列アイテムのいずれか2つの間にある場合、一致します
  • '%,$_GET[id]'配列がで終わる場合、一致します$_GET[id]
  • array = '$_GET[id]'match、配列に等しいアイテムが1つだけ含まれている場合$_GET[id]
于 2010-07-31T08:27:13.197 に答える
0

スキーマを正規化できない場合(これが最良のオプションです:

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

ただし、IDでレコードにアクセスする必要がある場合は、実際に正規化する必要があります

于 2010-07-31T09:40:10.407 に答える