MySQL SELECT 语句,其中值在数组中
MySQL SELECT statement where value is in array
我需要一些关于 MySQL 语句的帮助,但我无法真正做到这一点。
我有一个 table 这样的:
+---+-------------------------------+
|id | fruit |
+---+-------------------------------+
| 1 | apple,orange,pear,grape,lemon |
| 2 | pear,melon,apple,kiwi,lemon |
| 3 | orange,kiwi,pear,apple,cherry |
| 4 | grape,lemon,cherry,apple,melon|
+---+-------------------------------+
我需要做的是 SELECT 列 fruit
包含单词 melon
的所有行。有问题的单词可能在数组中的任何位置。
我厌倦了下面的查询,但出于某种原因我只得到 3-4 行,绝对不是全部:
$fruit = $_GET['fruit'];
$query1= "SELECT * FROM tbl_fruits WHERE ".$fruit." IN (fruit)";
如有任何意见,我们将不胜感激。
您可以使用FIND_IN_SET
SELECT * FROM tbl_fruits
WHERE find_in_set('$fruit', fruit)
但实际上您应该更改 table 设计。
永远不要在一个列中存储多个值!
更好的table设计是
fruits table
------------
id name
1 melon
2 orange
3 apple
...
products table
-------------------
id name price
1 P1 1.50
2 P2 2.99
3 P3 0.99
product_fruits table
--------------------
product_id fruit_id
1 1
1 2
2 2
3 1
这是经典的多对多关系(m 到 n)。
尝试以下 sql
$fruit = $_GET['fruit'];
$query1= "SELECT * FROM tbl_fruits WHERE fruit LIKE '%".$fruit."%'";
$fruit = $_GET['fruit'];
$query1= sprintf("SELECT * FROM tbl_fruits WHERE fruit LIKE '%%s%'",
mysql_real_escape_string($fruit ));
使用 LIKE
子句:
SELECT * FROM tbl_fruits
WHERE fruit LIKE '%apple%';
select * from tbl_fruits WHERE fruit like '%melon%'
如前所述,您 can/should 以不同的方式构建 table 结构。
这是 "relational database" 中的 "relational"。见 http://en.wikipedia.org/wiki/Database_normalization
一如既往:不是灵丹妙药。还有其他类型的数据库,并且可能有不规范化(部分)tables 的理由。但无论如何,这里有一个 sscce using PDO:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'localonly', 'localonly');
//echo 'client version: ', $pdo->getAttribute(PDO::ATTR_CLIENT_VERSION), "\n";
//echo 'server version: ', $pdo->getAttribute(PDO::ATTR_SERVER_VERSION), "\n";
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
setup($pdo);
$stmt = $pdo->prepare("
SELECT
m.name
FROM
soFruits as f
JOIN
soMixXFruits as x
ON
f.id=x.idFruit
JOIN
soFruitMix as m
ON
x.idMix=m.id
WHERE
f.name=?
");
$stmt->setFetchMode(PDO::FETCH_ASSOC);
foo($stmt, 'apple');
foo($stmt, 'melon');
function foo(PDOStatement $stmt, $param) {
echo "----- $param -----\r\n";
$stmt->execute( array($param) );
foreach($stmt as $r) {
echo join(', ', $r), "\r\n";
}
}
function setup($pdo) {
$queries = array(
'
CREATE TEMPORARY TABLE soFruits (
id INT auto_increment,
name varchar(64),
primary key(id)
)
',
'
CREATE TEMPORARY TABLE soFruitMix (
id INT auto_increment,
name varchar(32),
primary key(id)
)
',
'
CREATE TEMPORARY TABLE soMixXFruits (
idMix int,
idFruit int,
primary key(idMix, idFruit)
)
',
"INSERT INTO soFruits (id,name) VALUES (1,'apple'),(2,'cherry'),(3,'grape'),(4,'kiwi'),(5,'lemon'),(6,'melon'),(7,'orange'),(8,'pear')",
"INSERT INTO soFruitMix (id,name) VALUES (1, 'mix1'),(2,'mix2'),(3,'mix3'),(4,'mix4')",
);
foreach( $queries as $q ) {
$pdo->exec($q);
}
$data = [
'1'=>['apple','orange','pear','grape','lemon'],
'2'=>['pear','melon','apple','kiwi','lemon'],
'3'=>['orange','kiwi','pear','apple','cherry'],
'4'=>['grape','lemon','cherry','apple','melon']
];
$stmt = $pdo->prepare('
INSERT INTO soMixXFruits (idMix, idFruit)
SELECT
:idMix, id
FROM
soFruits
WHERE
name=:nameFruit
');
$stmt->bindParam('idMix', $idMix);
$stmt->bindParam('nameFruit', $nameFruit);
foreach($data as $idMix=>$mix) {
foreach($mix as $nameFruit) {
$stmt->execute();
}
}
}
看看 function setup($pdo)
中的 table 定义。你有像 fruits
和 mixes
这样的实体,然后有一个 table 代表它们的关系。
旁注:我没有注意指标。但对于通常至关重要的性能,请参阅 http://www.sitepoint.com/using-explain-to-write-better-mysql-queries/
我需要一些关于 MySQL 语句的帮助,但我无法真正做到这一点。
我有一个 table 这样的:
+---+-------------------------------+
|id | fruit |
+---+-------------------------------+
| 1 | apple,orange,pear,grape,lemon |
| 2 | pear,melon,apple,kiwi,lemon |
| 3 | orange,kiwi,pear,apple,cherry |
| 4 | grape,lemon,cherry,apple,melon|
+---+-------------------------------+
我需要做的是 SELECT 列 fruit
包含单词 melon
的所有行。有问题的单词可能在数组中的任何位置。
我厌倦了下面的查询,但出于某种原因我只得到 3-4 行,绝对不是全部:
$fruit = $_GET['fruit'];
$query1= "SELECT * FROM tbl_fruits WHERE ".$fruit." IN (fruit)";
如有任何意见,我们将不胜感激。
您可以使用FIND_IN_SET
SELECT * FROM tbl_fruits
WHERE find_in_set('$fruit', fruit)
但实际上您应该更改 table 设计。
永远不要在一个列中存储多个值!
更好的table设计是
fruits table
------------
id name
1 melon
2 orange
3 apple
...
products table
-------------------
id name price
1 P1 1.50
2 P2 2.99
3 P3 0.99
product_fruits table
--------------------
product_id fruit_id
1 1
1 2
2 2
3 1
这是经典的多对多关系(m 到 n)。
尝试以下 sql
$fruit = $_GET['fruit'];
$query1= "SELECT * FROM tbl_fruits WHERE fruit LIKE '%".$fruit."%'";
$fruit = $_GET['fruit'];
$query1= sprintf("SELECT * FROM tbl_fruits WHERE fruit LIKE '%%s%'",
mysql_real_escape_string($fruit ));
使用 LIKE
子句:
SELECT * FROM tbl_fruits
WHERE fruit LIKE '%apple%';
select * from tbl_fruits WHERE fruit like '%melon%'
如前所述,您 can/should 以不同的方式构建 table 结构。
这是 "relational database" 中的 "relational"。见 http://en.wikipedia.org/wiki/Database_normalization
一如既往:不是灵丹妙药。还有其他类型的数据库,并且可能有不规范化(部分)tables 的理由。但无论如何,这里有一个 sscce using PDO:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'localonly', 'localonly');
//echo 'client version: ', $pdo->getAttribute(PDO::ATTR_CLIENT_VERSION), "\n";
//echo 'server version: ', $pdo->getAttribute(PDO::ATTR_SERVER_VERSION), "\n";
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
setup($pdo);
$stmt = $pdo->prepare("
SELECT
m.name
FROM
soFruits as f
JOIN
soMixXFruits as x
ON
f.id=x.idFruit
JOIN
soFruitMix as m
ON
x.idMix=m.id
WHERE
f.name=?
");
$stmt->setFetchMode(PDO::FETCH_ASSOC);
foo($stmt, 'apple');
foo($stmt, 'melon');
function foo(PDOStatement $stmt, $param) {
echo "----- $param -----\r\n";
$stmt->execute( array($param) );
foreach($stmt as $r) {
echo join(', ', $r), "\r\n";
}
}
function setup($pdo) {
$queries = array(
'
CREATE TEMPORARY TABLE soFruits (
id INT auto_increment,
name varchar(64),
primary key(id)
)
',
'
CREATE TEMPORARY TABLE soFruitMix (
id INT auto_increment,
name varchar(32),
primary key(id)
)
',
'
CREATE TEMPORARY TABLE soMixXFruits (
idMix int,
idFruit int,
primary key(idMix, idFruit)
)
',
"INSERT INTO soFruits (id,name) VALUES (1,'apple'),(2,'cherry'),(3,'grape'),(4,'kiwi'),(5,'lemon'),(6,'melon'),(7,'orange'),(8,'pear')",
"INSERT INTO soFruitMix (id,name) VALUES (1, 'mix1'),(2,'mix2'),(3,'mix3'),(4,'mix4')",
);
foreach( $queries as $q ) {
$pdo->exec($q);
}
$data = [
'1'=>['apple','orange','pear','grape','lemon'],
'2'=>['pear','melon','apple','kiwi','lemon'],
'3'=>['orange','kiwi','pear','apple','cherry'],
'4'=>['grape','lemon','cherry','apple','melon']
];
$stmt = $pdo->prepare('
INSERT INTO soMixXFruits (idMix, idFruit)
SELECT
:idMix, id
FROM
soFruits
WHERE
name=:nameFruit
');
$stmt->bindParam('idMix', $idMix);
$stmt->bindParam('nameFruit', $nameFruit);
foreach($data as $idMix=>$mix) {
foreach($mix as $nameFruit) {
$stmt->execute();
}
}
}
看看 function setup($pdo)
中的 table 定义。你有像 fruits
和 mixes
这样的实体,然后有一个 table 代表它们的关系。
旁注:我没有注意指标。但对于通常至关重要的性能,请参阅 http://www.sitepoint.com/using-explain-to-write-better-mysql-queries/