Как обсуждалось в нашем чате, проблема вызвана миграцией сервера и новым сервером, использующим MySQL 5.7+, который по умолчанию включает only_full_group_by
.
Причина в том, что MySQL не может выбрать определитель значения, связанного с группировками, и выдает ошибки вместо того, чтобы молча игнорировать потенциально нежелательные значения в операторе SELECT
, как это было в предыдущих версиях MySQL.
Например: SELECT customer, SUM(order_total) FROM orders GROUP BY purchase_date
Если у двух или более клиентов одинаковый purchase_date
, может быть показан только один, и MySQL должен определить, какой из них вам нужен.
Поскольку CodeIgniter по умолчанию использует SELECT *
для оператора при использовании $this->db->get()
, возникает ошибка.
Чтобы решить эту проблему, настоятельно рекомендуется обновить все ваших запросов GROUP BY
во всем приложении, чтобы они были совместимы с MySQL 5.7. Это обеспечит получение правильных значений из ваших GROUP BY
утверждений.
Есть несколько вариантов, которые вы можете использовать, в порядке наименее сложных и наиболее полезных.
1) Используйте $this->db->count_all_results()
вместо $query->num_rows()
(он же: SELECT COUNT(*)
)
$this->db->where("savsoft_result.quid",$quid);
$this->db->group_by("savsoft_result.uid");
$res[0] = $this->db->count_all_results('savsoft_result');
$this->db->where("savsoft_result.quid",$quid);
$this->db->where("savsoft_result.uid !=",$uid);
$this->db->where("savsoft_result.score_obtained <=",$score);
$this->db->group_by("savsoft_result.uid");
$res[1] = $this->db->count_all_results('savsoft_result');
Обратите внимание на удаление order_by
, так как он не нужен для подсчета строк.
2) Ограничить значения только теми, которые сгруппированы
$this->db->select('savsoft_result.uid');
$this->db->where("savsoft_result.quid",$quid);
$this->db->group_by("savsoft_result.uid");
$this->db->order_by("savsoft_result.score_obtained",'DESC');
$query = $this->db->get('savsoft_result');
$res[0] = $query->num_rows();
$this->db->select('savsoft_result.uid');
$this->db->where("savsoft_result.quid",$quid);
$this->db->where("savsoft_result.uid !=",$uid);
$this->db->where("savsoft_result.score_obtained <=",$score);
$this->db->group_by("savsoft_result.uid");
$this->db->order_by("savsoft_result.score_obtained",'DESC');
$querys = $this->db->get('savsoft_result');
$res[1] = $querys->num_rows();
3) Явно определите ANY_VALUE
для всех несгруппированных столбцов
(это эквивалент отключения only_full_group_by
)
Используя запрос, который я предоставил выше.
SELECT ANY_VALUE(customer), SUM(order_total) FROM orders GROUP BY purchase_date
Так что вы должны иметь возможность использовать что-то вроде следующего, обязательно добавьте ВСЕ не сгруппированные столбцы в связанной таблице.
$this->db->select('ANY_VALUE(savsoft_result.quid), ANY_VALUE(savsoft_result.score_obtained), savsoft_result.uid');
$this->db->where("savsoft_result.quid",$quid);
$this->db->group_by("savsoft_result.uid");
$this->db->order_by("savsoft_result.score_obtained",'DESC');
$query = $this -> db -> get('savsoft_result');
$res[0] = $query->num_rows();
$this->db->select('ANY_VALUE(savsoft_result.quid), ANY_VALUE(savsoft_result.score_obtained), savsoft_result.uid');
$this->db->where("savsoft_result.quid",$quid);
$this->db->where("savsoft_result.uid !=",$uid);
$this->db->where("savsoft_result.score_obtained <=",$score);
$this->db->group_by("savsoft_result.uid");
$this->db->order_by("savsoft_result.score_obtained",'DESC');
$querys = $this->db->get('savsoft_result');
$res[1] = $querys->num_rows();
В качестве альтернативы вы можете отключить only_full_group_by
sql_mode.
Вы можете временно отключить его, обновив глобальную переменную, выполнив оператор SET GLOBAL
.
SET GLOBAL sql_mode=(SELECT TRIM(BOTH ',' FROM REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','')));
Это извлечет используемый в настоящее время sql_mode
и удалит часть ONLY_FULL_GROUP_BY
, затем удалит все оставшиеся начальные или конечные запятые. Однако после перезапуска службы MySQL вам нужно будет снова выполнить оператор.
Чтобы гарантировать, что only_full_group_by
не вернется к включенному при перезапуске службы MySQL, отредактируйте ваш файл конфигурации my.cnf
MySQL, чтобы опустить ONLY_FULL_GROUP_BY
в объявлении sql_mode
.
Вы можете получить текущий sql_mode
, выполнив инструкцию
SHOW VARIABLES LIKE 'sql_mode';
Что должно возвращать что-то вроде:
ONLY_FULL_GROUP_BY,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_VALUE_ON_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Скопируйте весь текст, затем объявите sql_mode
в файле my.cnf
, удалив часть ONLY_FULL_GROUP_BY
.
[mysqld]
sql_mode=ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_VALUE_ON_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
После внесения изменений в файл my.cnf
перезапустите службу MySQL.