Группировка предложений WHERE в Codeigniter - PullRequest
16 голосов
/ 24 июня 2011

Я хочу создать следующий код SQL с использованием Active Records в Codeigniter:

WHERE name != 'Joe' AND (age < 69 OR id > 50)

Кажется, что я могу сделать следующее, я не могу понять, как их сгруппировать

$this->db->select()->from('users')->where('name !=', 'Joe')->where('age <', 69)->or_where('id <', $id); 

Есть идеи? Мой SQL-запрос слишком сложен, поэтому я не хочу переписывать все на традиционном SQL.

UPDATE

Мой код SQL генерируется динамически в зависимости от значений определенных параметров, передаваемых в метод модели. Проблема с невозможностью использовать круглые скобки вызывает проблему, потому что приоритет оператора таков, что AND вычисляется первым перед OR.

* Вот фрагмент моего кода активных записей, где есть некоторый другой код до и после него:

            ... some $this->db->where() ...
            ... some $this->db->where() ...

    if($price_range) {
        $price_array = explode('.', $price_range);
        for($i = 0; $i < count($price_array); $i++) {
            if($i == 0) {
                $this->db->where('places.price_range', $price_array[$i]);
            } else {
                $this->db->or_where('places.price_range', $price_array[$i]);
            }
        }

    }

            ... some $this->db->where() ...
            ... some $this->db->where() ...

Проблема возникает из-за того, что я использую $this->db->or_where(), который вводит предложение OR, которое выбрасывает приоритет оператора в беспорядок, не имея возможности использовать ( ) для изменения порядка.

** Есть ли способ решить это? **

Ответы [ 6 ]

21 голосов
/ 20 января 2016

В Codeigniter 3.0.3 вы можете сделать это просто так:

$this->db->select()
  ->from('users')
  ->where('name !=', 'Joe')
  ->group_start() // Open bracket
  ->where('age <', 69)
  ->or_where('id <', $id)
  ->group_end(); // Close bracket

Возможно, это может помочь

15 голосов
/ 24 июня 2011

Вы можете использовать одну большую строку.

$this->db->select()->from('users')->where("name != 'Joe' AND (age < 69 OR id > 50) ");

13 голосов
/ 18 апреля 2013

Группировка предложений where не входит в CI по умолчанию.Вы должны расширить ядро ​​и добавить в способность.Я сделал это следующим образом:

class MY_DB_mysql_driver extends CI_DB_mysql_driver 
{       
    public function __construct($params) 
    {
    parent::__construct($params);
    }
    /** 
     * This function will allow you to do complex group where clauses in to c and (a AND b) or ( d and e)
     * This function is needed as else the where clause will append an automatic AND in front of each where Thus if you wanted to do something
     * like a AND ((b AND c) OR (d AND e)) you won't be able to as the where would insert it as a AND (AND (b...)) which is incorrect. 
     * Usage: start_group_where(key,value)->where(key,value)->close_group_where() or complex queries like
     *        open_bracket()->start_group_where(key,value)->where(key,value)->close_group_where()
     *        ->start_group_where(key,value,'','OR')->close_group_where()->close_bracket() would produce AND ((a AND b) OR (d))
     * @param $key mixed the table columns prefix.columnname
     * @param $value mixed the value of the key
     * @param $escape string any escape as per CI
     * @param $type the TYPE of query. By default it is set to 'AND' 
     * @return db object.  
     */
    function start_group_where($key,$value=NULL,$escape,$type="AND")
    {
        $this->open_bracket($type); 
        return parent::_where($key, $value,'',$escape); 
    }

    /**
     * Strictly used to have a consistent close function as the start_group_where. This essentially callse the close_bracket() function. 
     */
    function close_group_where()
    {
        return $this->close_bracket();  
    }

    /**
     * Allows to place a simple ( in a query and prepend it with the $type if needed. 
     * @param $type string add a ( to a query and prepend it with type. Default is $type. 
     * @param $return db object. 
     */
    function open_bracket($type="AND")
    {
        $this->ar_where[] = $type . " (";
        return $this;  
    }   

    /**
     * Allows to place a simple ) to a query. 
     */
    function close_bracket()
    {
        $this->ar_where[] = ")"; 
        return $this;       
    }
}

Использование:

group_where_start(key,value)->where(key,value)->group_where_close() 

или

сложные запросы типа

open_bracket()->start_group_where(key,value)->where(key,value)->close_group_where()->start_group_where(key,value,'','OR')->close_group_where()->close_bracket() would produce AND ((a AND b) OR (d))
7 голосов
/ 24 июня 2011

Что я сделал, так это продублировал предложение and после where, что фактически совпадает с выбором длинной строки.

$this->db->select()
  ->from('users')
  ->where('name !=', 'Joe')
  ->where('age <', 69)
  ->or_where('id <', $id)
  ->where('name !=', 'Joe');

Один большой струнный путь, вероятно, лучше.

5 голосов
/ 23 мая 2017

CI3 имеет все, что вам нужно!

$this->db->select('*')->from('my_table')
        ->group_start()
                ->where('a', 'a')
                ->or_group_start()
                        ->where('b', 'b')
                        ->where('c', 'c')
                ->group_end()
        ->group_end()
        ->where('d', 'd')
->get();

https://www.codeigniter.com/userguide3/database/query_builder.html#query-grouping

0 голосов
/ 24 июня 2011

решаемая. Динамически генерируйте запрос SQL и вставьте его в $this->db->where(). Спасибо, ребята!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...