MySQL SELECT 语句,其中值在数组中

Posted

技术标签:

【中文标题】MySQL SELECT 语句,其中值在数组中【英文标题】:MySQL SELECT statement where value is in array 【发布时间】:2015-04-03 20:53:59 【问题描述】:

我需要一些关于我无法真正工作的 mysql 语句的帮助。

我有一张这样的桌子:

+---+-------------------------------+
|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|
+---+-------------------------------+

我需要做的是选择列fruit 包含单词melon 的所有行。有问题的单词可能位于数组中的任何位置。

我厌倦了下面的查询,但由于某种原因,我只得到 3-4 行,绝对不是全部:

$fruit = $_GET['fruit'];
$query1= "SELECT * FROM tbl_fruits WHERE ".$fruit." IN (fruit)";

我们将不胜感激。

【问题讨论】:

关于您的编码风格:从不使用字符串连接进行查询。 SELECT * FROM tbl_fruits WHERE find_in_set('$fruit',fruit) 在查询中捕获它 @meskobalazs,点了。我可以麻烦您解释一下为什么不应该这样做。如您所见,我仍在学习,因此任何能带来一些知识的 cmets 都会受到赞赏。 【参考方案1】:

您可以使用FIND_IN_SET

SELECT * FROM tbl_fruits 
WHERE find_in_set('$fruit', fruit)

但实际上你应该改变你的桌子设计。

切勿在单个列中存储多个值!

更好的表格设计应该是

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

【讨论】:

效果很好,谢谢你。在表格设计中,我决定这样做,因为我有 4 列,每列包含 5 个值。所以我必须在有 20 个不同的列(每个值一个)或只有 4 个列和一个包含 5 个值的数组之间做出选择。出于简单的原因,第二个选项似乎是更好的选择。 我将答案扩展到一个更好的表格设计。给我一分钟 你原来的表的名称和用途是什么? 该表包含产品列表 - 大约 17000 行。所以每个产品都有一个标签。然后我将显示共享相同标签的产品列表。因此,带有标签apple 的产品与苹果等一起出现在列表中。以同样的方式,我还有 3 个列,每个列有 5 个标签,用于在整个网站的其他相关页面上显示产品。【参考方案2】:

如前所述,您可以/应该以不同的方式构建表结构。 它是“关系数据库”中的“关系”。见http://en.wikipedia.org/wiki/Database_normalization

一如既往:不是灵丹妙药。还有其他类型的数据库,并且可能存在不规范化(部分)表的原因。但无论如何,这是一个使用PDO 的sscce:

<?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) 中的表定义。你有像fruitsmixes 这样的实体,然后有一个代表它们关系的表。

旁注:我没有注意指标。但对于通常至关重要的性能,请参阅http://www.sitepoint.com/using-explain-to-write-better-mysql-queries/

【讨论】:

【参考方案3】:
$fruit = $_GET['fruit'];
$query1= sprintf("SELECT * FROM tbl_fruits WHERE fruit LIKE '%%s%'",
        mysql_real_escape_string($fruit ));

【讨论】:

@Robert 我认为现在它的 sql 注入是免费的。 在您编辑后它是,但当我发表评论时它不是。现在编码不会编译顺便说一句。语法错误。【参考方案4】:
select * from tbl_fruits WHERE fruit like '%melon%'

【讨论】:

这也能抓住“西瓜”。现在,如果 OP 能够用逗号开始和结束他的所有字符串,那么它们看起来像 ,apple,orange,pear,grape,lemon,,那么他可以使用 like '%,melon,%'【参考方案5】:

使用LIKE 子句:

SELECT * FROM tbl_fruits
    WHERE fruit LIKE '%apple%';

【讨论】:

【参考方案6】:

试试下面的sql

$fruit = $_GET['fruit'];
$query1= "SELECT * FROM tbl_fruits WHERE fruit LIKE '%".$fruit."%'";

【讨论】:

以上是关于MySQL SELECT 语句,其中值在数组中的主要内容,如果未能解决你的问题,请参考以下文章

MySQL - 如何选择值在数组中的行?

数据库中某项其中一个值在该项排第几,php+mysql

PHP Array into mysql select 语句

根据其他列 PSQL 的值在 SELECT 语句中添加附加列

mysql 一个字段中有a,b 怎么调用其中一个

mysql explain详解