How can I emulate WHERE 1 in a dynamic query?

淺唱寂寞╮ 提交于 2019-12-11 07:08:46

问题


I'm making a query dynamically like this:

$query = "SELECT u.*
          FROM users u
          WHERE date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 $range))";

Also $range contains a word like this:

switch ($_GET['range']){
   case "week":
      $range = "WEEK";
   case "month":
      $range = "MONTH";
   case "year":
      $range = "YEAR";
   case "ALL":
      $range = <I don't know what should I put here to get the expected result>;
}

As I've said above, I want to set something as $range value to make the WHERE clause something like WHERE 1. How can I do that?


回答1:


I think what Adam was suggesting is something like this:

$where = '';

switch ($_GET['range']) {

    case "week":
       $where = "date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 WEEK))":
        break;

    case "month":
       $where = "date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 MONTH))":
        break;

    case "year":
       $where = "date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 YEAR))":
        break;

    default:
        $where = '';
}

$query = "SELECT u.* FROM users u WHERE $where";

Assume reporting with other criteria? Where the string concatenation gets messy. Adding 'AND' between parts. Suppressing WHERE keyword entirely? Where OOP code to represent the SQL query can be useful.




回答2:


Perhaps use a case statement in your where clause?

 $query = "SELECT u.*
           FROM users u
           WHERE CASE {$range}
                 WHEN 'ALL' then TRUE
                 ELSE date_time > unix_timestamp(DATE_SUB(now()
                                  , INTERVAL 1 {$range}))
                 END";



回答3:


switch ($_GET['range']){
  case "week":
  $range = "WEEK";
 case "month":
  $range = "MONTH";
 case "year":
  $range = "YEAR";
 case "ALL":
  $range = null;
}

$query = "SELECT u.*
      FROM users u
      WHERE 1=1 ";
if(!empty($range)) {
  $query .= " AND date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 $range))";
}

Add datetime where clause conditionally; WHERE 1=1 will always be true. So the next condition's result will matter on the final result




回答4:


Let's start with the fact that your switch statement doesn't have break statements and isn't going to work the way you expect.

Here is what I'd suggest:

$query = "SELECT u.*
          FROM users u";

$range = false;

if (isset($_GET['range'])) {    
    switch ($_GET['range']){
       case "week":
          $range = "WEEK";
          break;
       case "month":
          $range = "MONTH";
          break;
       case "year":
          $range = "YEAR";
          break;
       default:
          $range = false;
    }
} 


if ($range) {
  $query .= " WHERE date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 $range))";
}



回答5:


I would define an array with valid ranges and validate the user input first. Then build the query dynamicly.

$validRanges = [
    'year'  => 'YEAR',
    'month' => 'MONTH',
    'week'  => 'WEEK',
    'ALL'   => null
];

if (isset($_GET['range']) && !isset($validRanges[$_GET['range']])) {
    $range = $validRanges[$_GET['range']]);
} else {
    // it's up to you, what to do in this case
    throw new Exception('Range is not valid or missing');
}

if ($range === null) {
    $rangeCondition = '1=1';
} else {
    $rangeCondition = "date_time > unix_timestamp(NOW() - INTERVAL 1 $range)";
}

$query = "SELECT u.*
          FROM users u
          WHERE $rangeCondition";


来源:https://stackoverflow.com/questions/45468750/how-can-i-emulate-where-1-in-a-dynamic-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!