1

I need some help with an MySQL statement that I cannot really make to work.

I have a table like this:

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

What I need to do is to SELECT all rows where the column fruit contains the word melon. The word in question might be at any position in the array.

I tired with the below query but for some reason I only get 3-4 rows, definitely not all of them:

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

Any comments will be appreciated.

user3132858
  • 609
  • 1
  • 11
  • 27

6 Answers6

10

You can use FIND_IN_SET

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

But you actually should rather change your table design.

Never store multiple values in a single column!

A better table design would be

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

That is a classic many to many relation (m to n).

juergen d
  • 201,996
  • 37
  • 293
  • 362
  • that work great, thank you juergen. On the table design, I have decided to do it like this since I have 4 columns containing 5 values each. so I had to choose between having 20 different columns, one for each value or having only 4 columns with an array with 5 values. Second option seemed like a better choice for simplicity reasons. – user3132858 Feb 04 '15 at 11:07
  • I expand my answer to a table design that would be better. Give me a minuite – juergen d Feb 04 '15 at 11:07
  • What is the name and purpose of your original table? – juergen d Feb 04 '15 at 11:09
  • The table contains a list of products - about 17000 rows. So each product has a tag attached to it. Then I am showing a list of products that share the same tag. So products that have the tag `apple` appear in the list with apples and so on. In the same fashion I have 3 more columns with 5 tags each that display the product on other relevant pages throughout the website. – user3132858 Feb 04 '15 at 11:24
2
$fruit = $_GET['fruit'];
$query1= sprintf("SELECT * FROM tbl_fruits WHERE fruit LIKE '%%s%'",
        mysql_real_escape_string($fruit ));
harry
  • 1,007
  • 2
  • 10
  • 19
0

Try below sql

$fruit = $_GET['fruit'];
$query1= "SELECT * FROM tbl_fruits WHERE fruit LIKE '%".$fruit."%'";
v2solutions.com
  • 1,439
  • 9
  • 8
0

Use a LIKE clause:

SELECT * FROM tbl_fruits
    WHERE fruit LIKE '%apple%';
Savv
  • 433
  • 2
  • 7
0
select * from tbl_fruits WHERE fruit like '%melon%'
웃웃웃웃웃
  • 11,829
  • 15
  • 59
  • 91
mikepanda
  • 3
  • 2
  • That would also catch "watermelon". Now, if the OP was able to start and end all of his string with commas so they looked like `,apple,orange,pear,grape,lemon,`, then he could use a `like '%,melon,%'` – Jeremy J Starcher Feb 04 '15 at 14:48
0

As mentioned before you can/should build your table structure differently.
It's the "relational" in "relational database". see http://en.wikipedia.org/wiki/Database_normalization

As always: not a silver bullet. There are other kinds of daabases and there can be rasons for not normalizing (parts of) tables. But anyway, here's an 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();
        }
    }
}

Take a look at the table definitions in function setup($pdo). You have entities like fruits and mixes and then there's a table that represents their relationship.

side-note: I didn't pay attention to the indicies. But for performance that is usually crucial, see http://www.sitepoint.com/using-explain-to-write-better-mysql-queries/

VolkerK
  • 95,432
  • 20
  • 163
  • 226