简体   繁体   中英

Cleaner way to write this MySql query

I generate below query through php

$sql .= "Select * from test";

$sub_sql = '';

foreach($value as $n_k => $n_v)
{
    switch($n_v)
    {
        case '1':
            $sub_sql .= " OR (id = 1 )"; 
        break;
        case '2':
            $sub_sql .= " OR (category = 4) ";
        break;
        case '3':
            $sub_sql .= " OR (location = 'U.S.') ";
        break;  
    }
}

if($sub_sql != '')
{
    $sql .= " where ( 0 ".$sub_sql." ) ";
}

$sql .= "GROUP BY id  ORDER BY stored_date DESC LIMIT 0, 5 ";

But as you'll can see where $subsql is concatenated to $sql , that part looks really messy. Evn though it works fine but it looks really poor. Can anyone pls help me with this?

Is this a simplified example? Because I see no reason not to simplify it like this:

$sql .= "Select * from test where a=1";

foreach($value as $n_k => $n_v)
{
    switch($n_v)
    {
        case '1':
            $sql .= " AND (id = 1 )"; 
        break;
        case '2':
            $sql .= " AND (category = 4)";
        break;
        case '3':
            $sql .= " AND (location = 'U.S.')";
        break;  
    }
}

$sql .= " ORDER BY stored_date DESC LIMIT 0, 5 ";

Note, that I removed the GROUP BY from your statement. You shouldn't use it, if you don't use aggregate functions. Group by collapses group of rows and displays random rows from each group. If you have a need to remove duplicate rows, consider to use the DISTINCT keyword in the SELECT clause.

UPDATE:

Your new version can be shortened like this:

$sql .= "Select * from test";

foreach($value as $n_k => $n_v)
{
    switch($n_v)
    {
        case '1':
            $sql .= " where (id = 1 ) "; 
        break;
        case '2':
            $sql .= " where (category = 4) ";
        break;
        case '3':
            $sql .= " where (location = 'U.S.') ";
        break;  
    }
}

$sql .= " GROUP BY id  ORDER BY stored_date DESC LIMIT 0, 5 ";

Basically it comes down to this. If you have to add multiple AND conditions, you always add a WHERE 1=1 (if you have no other fix (non-dynamic) conditions) to the query. It doesn't change anything, the optimizer will throw it away again. But you can easily append as many conditions as you want. That's what I did in my original answer before your edit. Note though, that you can not just append OR whatever = true when you are mixing AND and OR conditions. You will have to use parantheses to not get a false resultset. This is where your (0 OR ...) thing comes from. Since you only have 1 condition, there's no need at all for all I said right now. Just add it as WHERE whatever = true and that's it.

How about adding the conditions to the sql?

Something like:

Select * from test where a=1
AND 
(
  ($n_v = 1 AND id = 1)
  OR
  ($n_v = 2 AND category = 4)
  OR
  ($n_v = 3 AND location = 'U.S.')
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2025 STACKOOM.COM