Programming

MySql에서 쿼리를 실행할 때 only_full_group_by와 관련된 오류

procodes 2020. 2. 25. 22:57
반응형

MySql에서 쿼리를 실행할 때 only_full_group_by와 관련된 오류


시스템을 업그레이드하고 작업중 인 웹 응용 프로그램 용 PHP로 MySql 5.7.9를 설치했습니다. 동적으로 생성 된 쿼리가 있으며 이전 버전의 MySql에서 실행될 때 정상적으로 작동합니다. 5.7로 업그레이드 한 후이 오류가 발생합니다.

SELECT 목록의 식 # 1은 GROUP BY 절에 없으며 GROUP BY 절의 열에 기능적으로 종속되지 않는 집계되지 않은 열 'support_desk.mod_users_groups.group_id'를 포함합니다. sql_mode = only_full_group_by와 호환되지 않습니다

서버 SQL 모드 주제에서 Mysql 5.7의 매뉴얼 페이지를 참고하십시오 .

이것은 나에게 문제를 일으키는 쿼리입니다.

SELECT mod_users_groups.group_id AS 'value', 
       group_name AS 'text' 
FROM mod_users_groups
LEFT JOIN mod_users_data ON mod_users_groups.group_id = mod_users_data.group_id 
WHERE  mod_users_groups.active = 1 
  AND mod_users_groups.department_id = 1 
  AND mod_users_groups.manage_work_orders = 1 
  AND group_name != 'root' 
  AND group_name != 'superuser' 
GROUP BY group_name 
HAVING COUNT(`user_id`) > 0 
ORDER BY group_name

이 문제에 대해 인터넷 검색을 수행했지만 only_full_group_by쿼리를 수정하기 위해 수행해야 할 작업을 파악할 만큼 충분히 이해하지 못했습니다 . only_full_group_by옵션을 끌 수 있습니까 ? 아니면 다른 조치가 필요합니까?

더 자세한 정보가 필요하면 알려주십시오.


난 그냥 추가 할 group_id받는 사람 GROUP BY.

하면 SELECT의 일부가 열 보내고 GROUP BY그룹 내의 그 열에 대한 복수의 값이있을 수 있지만, 단지 하나의 결과 값을위한 공간이있을 것이다. 따라서 데이터베이스는 일반적으로 여러 값을 하나의 값으로 만드는 방법을 정확하게 알려야합니다. 일반적으로,이이 같은 집계 함수와 함께 이루어집니다 COUNT(), SUM(), MAX()등 ... 내가 말할 일반적으로 대부분의 다른 인기있는 데이터베이스 시스템이 주장하기 때문이다. 그러나 버전 5.7 이전의 MySQL에서는 기본 동작이 불평하지 않고 임의로 값을 선택하기 때문에 더 관대했습니다 ! 그것은 또한ANY_VALUE()이전과 동일한 동작이 필요한 경우이 질문에 대한 다른 솔루션으로 사용할 수있는 함수입니다. 이 유연성은 비결정 적이기 때문에 비용이 많이 들기 때문에 필요한 이유가 없다면 권장하지 않습니다. MySQL은 이제 only_full_group_by좋은 이유로 기본적으로 설정을 설정하고 있으므로 익숙해 져 쿼리를 준수하는 것이 가장 좋습니다.

왜 내 간단한 대답이 위입니까? 나는 몇 가지 가정을 만들었습니다.

1) group_id는 독특합니다. 합리적인 것처럼 보이며 결국 'ID'입니다.

2) group_name또한 독특합니다. 이것은 그렇게 합리적인 가정이 아닐 수도 있습니다. 그렇지 않은 경우 중복 된 부분이 group_names있고 내 조언에 따라에 추가 group_id하면 GROUP BY이름이 같은 그룹에 결과에 별도의 행이 있으므로 이전보다 더 많은 결과를 얻을 수 있습니다. 데이터베이스가 임의로 값을 임의로 선택했기 때문에 중복 그룹을 숨기는 것보다 나을 것입니다.

또한 둘 이상의 테이블이 관련된 경우 모든 열을 테이블 이름 또는 별명으로 규정하는 것이 좋습니다.

SELECT 
  g.group_id AS 'value', 
  g.group_name AS 'text' 
FROM mod_users_groups g
LEFT JOIN mod_users_data d ON g.group_id = d.group_id 
WHERE g.active = 1 
  AND g.department_id = 1 
  AND g.manage_work_orders = 1 
  AND g.group_name != 'root' 
  AND g.group_name != 'superuser' 
GROUP BY 
  g.group_name, 
  g.group_id 
HAVING COUNT(d.user_id) > 0 
ORDER BY g.group_name

only_full_group_by다음을 실행하여 설정 을 비활성화 할 수 있습니다 .

mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
mysql> set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

MySQL 8은 NO_AUTO_CREATE_USER제거 할 필요 가 없으므로 허용하지 않습니다 .


다른 답변에 설명 된대로 경고 메시지를 끄거나 진행 상황을 이해 하고 수정할 수 있습니다.

MySQL 5.7.5부터 기본 SQL 모드에는 ONLY_FULL_GROUP_BY포함되어 있습니다. 이는 행을 그룹화 한 다음 해당 그룹에서 무언가를 선택할 때 선택해야 할 명시 적으로 말해야 합니다.MySQL은 당신이 찾고있는 그룹의 어떤 행을 알아야하며, 두 가지 옵션이 있습니다

MySQL은 당신이 찾고있는 그룹의 어떤 행을 알아야하며, 두 가지 옵션이 있습니다

  • 원하는 열을 그룹 문에 추가 할 수도 있습니다. group by rect.color, rect.value어떤 경우에는 원하지 않을 수도있는 동일한 색상으로 중복 결과를 반환 할 수 있습니다
  • mysql의 집계 함수사용 하여 전체 목록 과 같이 그룹 내에서 찾고있는 행을 나타낼 수도 있습니다AVG() MIN() MAX()
  • 마지막으로 ANY_VALUE()그룹 내부의 모든 결과가 동일한 지 확인할 수 있습니다. 문서

현재 검색어를 변경하지 않으려면 아래 단계를 따르십시오.

  1. 당신의 상자에 방랑 ssh
  2. 유형: sudo vim /etc/mysql/my.cnf
  3. 파일 하단으로 스크롤하여 입력 A하여 삽입 모드로 들어갑니다.
  4. 복사 및 붙여 넣기

    [mysqld]
    sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    
  5. 입력 esc종료 입력 모드로

  6. :wqvim을 저장하고 닫으려면 입력하십시오 .
  7. sudo service mysql restartMySQL을 다시 시작하려면 입력하십시오 .

ANY_VALUE()집계되지 않은 열을 참조하는 데 사용 합니다.

에서 의 MySQL 5.7 문서 :

집계되지 않은 열을 참조하는 데 ONLY_FULL_GROUP_BY사용하여 비활성화하지 않고도 동일한 효과를 얻을 수 있습니다 ANY_VALUE().

...

ONLY_FULL_GROUP_BY선택 목록의 집계되지 않은 주소 열이 GROUP BY에서 이름이 지정되지 않았으므로이 쿼리는 사용으로 유효하지 않을 수 있습니다 .

SELECT name, address, MAX(age) FROM t GROUP BY name;

...

주어진 데이터 세트에 대해 실제로 각 이름 값이 실제로 주소 값을 고유하게 결정하는 경우 주소는 사실상 기능적으로 이름에 의존합니다. MySQL에게 쿼리를 수락하도록하려면 다음 ANY_VALUE()함수를 사용할 수 있습니다 .

SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;

이 오류가 무엇인지 설명하려고 노력할 것입니다.
MySQL 5.7.5부터 옵션 ONLY_FULL_GROUP_BY이 기본적으로 활성화되어 있습니다.
따라서 표준 SQL92 이하에 따르면 :

선택 목록, HAVING 조건 또는 ORDER BY 목록이 GROUP BY 절에 이름이 지정되지 않았거나 기능적으로 GROUP BY 열에 종속되지 않은 집계되지 않은 열을 참조하는 쿼리는 허용하지 않습니다.

( 문서에서 더 읽기 )

예를 들어,

SELECT * FROM `users` GROUP BY `name`;

위의 쿼리를 실행하면 오류 메시지가 나타납니다.

# 1055-SELECT 목록의 식 # 1은 GROUP BY 절에 없으며 GROUP BY 절의 열에 기능적으로 의존하지 않는 집계되지 않은 열 'testsite.user.id'를 포함합니다. sql_mode = only_full_group_by와 호환되지 않습니다

왜?
MySQL은 정확히 이해하지 못하기 때문에 그룹화 된 레코드에서 검색 할 특정 값이 무엇인지, 이것이 요점입니다.

IE는 users테이블 에이 레코드가 있다고 말할 수 있습니다 .
에야디야

그리고 위에 표시된 잘못된 쿼리를 실행합니다.
그리고 name과 함께 3 개의 레코드가 John있고 훌륭 하기 때문에 위에 표시된 오류가 발생 하지만 모두 email필드 값 이 다릅니다 .
따라서 MySQL은 그룹화 된 레코드로 반환 할 대상을 이해하지 못합니다.

다음과 같이 간단히 쿼리를 변경하여이 문제를 해결할 수 있습니다.

SELECT `name` FROM `users` GROUP BY `name`

또한 SELECT 섹션에 더 많은 필드를 추가하고 싶을 수도 있지만 집계되지 않은 경우 사용할 수는 있지만 사용할 수는 없습니다 (그러나 권장하지는 않음).

SELECT ANY_VALUE(`id`), ANY_VALUE(`email`), `name` FROM `users` GROUP BY `name`

여기에 이미지 설명을 입력하십시오

이제 왜 사용을 ANY_VALUE권장하지 않는지 묻습니다 .
MySQL은 그룹화 된 레코드의 값을 정확히 알지 못하기 때문에이 기능을 사용하여 레코드를 가져 오도록 요청합니다 (이 경우 이름이 John 인 첫 번째 레코드의 전자 메일을 가져 왔습니다).
나는 왜 당신이이 행동이 존재하기를 원하는지에 대한 아이디어를 내놓을 수 없습니다.

나를 이해하지 못하면 MySQL에서 그룹화가 어떻게 작동하는지 자세히 읽어보십시오. 매우 간단합니다.

그리고 마지막으로, 여기에 하나 더 간단하지만 유효한 쿼리가 있습니다.
사용 가능한 연령에 따라 총 사용자 수를 쿼리하려면이 쿼리를 작성하십시오.

SELECT `age`, COUNT(`age`) FROM `users` GROUP BY `age`;

MySQL 규칙에 따라 완전히 유효합니다.
등등.

문제가 정확히 무엇인지 이해하고 해결책을 적어 두는 것이 중요합니다.


나는 laravel homestead (0.5.0, Laravel 5.3, mysql 5.7.12)를 사용하고 있습니다.

/etc/mysql/my.cnf반영 하도록 편집 명시 적으로 설정 한 후에도 :

[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

여전히 오류가 발생했습니다.

나는 변경했습니다 config/database.php에서 truefalse:

    'mysql' => [
        'strict' => false, //behave like 5.6
        //'strict' => true //behave like 5.7
    ], 

더 읽을 거리 :

https://laracasts.com/discuss/channels/servers/set-set-sql-mode-on-homestead https://mattstauffer.co/blog/strict-mode-and-other-mysql-customizations-in-laravel -5-2


wamp 3.0.6 또는 안정 2.5 이외의 상위 버전을 사용하는 경우이 문제가 발생할 수 있습니다. 먼저 sql 문제입니다. 그에 따라 필드 이름을 지정해야합니다. 그러나 다른 방법으로 해결할 수 있습니다. wamp의 녹색 아이콘을 클릭하십시오. mysql-> mysql 설정-> sql_mode-> 없음. 또는 콘솔에서 기본값을 변경할 수 있습니다.

mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
mysql> set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

파일에 줄 추가 (아래 설명) : /etc/mysql/my.cnf

[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

나를 위해 잘 작동하십시오. 서버 버전 : 5.7.18-0ubuntu0.16.04.1-(우분투)


맥의 경우 :

1. 기본 my-default.cnf를 /etc/my.cnf에 복사하십시오.

sudo cp $(brew --prefix mysql)/support-files/my-default.cnf /etc/my.cnf

2. 좋아하는 편집기를 사용하여 my.cnf에서 sql_mode를 변경하고 이것을 설정하십시오.

sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

3. MySQL 서버를 다시 시작하십시오.

mysql.server restart

localhost / wampserver 3의 경우이 오류를 제거하기 위해 sql-mode = user_mode를 설정할 수 있습니다.

click on wamp icon -> MySql -> MySql Setting -> sql-mode -> user_mode

그런 다음 늪이나 아파치를 다시 시작하십시오.


이것이 전체 문제를 이해하는 데 도움이 된 것입니다.

  1. https://stackoverflow.com/a/20074634/1066234
  2. https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

다음은 문제가되는 쿼리의 다른 예입니다.

문제가있는 :

SELECT COUNT(*) as attempts, SUM(elapsed) as elapsedtotal, userid, timestamp, questionid, answerid, SUM(correct) as correct, elapsed, ipaddress FROM `gameplay`
                        WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY)
                        AND cookieid = #

이것을 끝에 추가하여 해결했습니다.

  GROUP BY timestamp, userid, cookieid, questionid, answerid, elapsed, ipaddress

참고 : PHP의 오류 메시지를 참조하십시오. 문제의 위치를 ​​알려줍니다.

예:

MySQL 쿼리 오류 1140 : GROUP BY가없는 집계 된 쿼리에서 SELECT 목록의 식 # 4는 집계되지 않은 열 'db.gameplay.timestamp'를 포함합니다. sql_mode = only_full_group_by와 호환되지 않음-쿼리 : 시도로 SELECT COUNT (*), 경과로 표시된 SUM (elapsed), userid, timestamp, questionid, answerid, SUM (correct)로 정확, 경과, ipaddress FROM gameplay WHERE timestamp> = DATE_SUB (NOW (), INTERVAL 1 DAY) AND userid = 1

이 경우 GROUP BY에서 식 # 4 가 누락되었습니다.


당신은 추가 할 수 있습니다 unique index합니다 group_id; 당신은 그것이 group_id독특 하다고 확신한다면 .

쿼리를 수정하지 않고도 사례를 해결할 수 있습니다 .

답변이 늦었지만 답변에 아직 언급되지 않았습니다. 사용 가능한 이미 포괄적 인 답변을 완료해야 할 수도 있습니다. 적어도 필드가 너무 많은 테이블을 분할해야 할 때 적어도 내 경우를 해결했습니다.


doctrine query builder를 사용하여 Symfony 에이 오류가 있고이 오류가 orderBy 에 의해 발생한 경우 :

select원하는 열에 주의를 기울이고 대신에 groupBy사용하십시오 .addGroupBygroupBy

$query = $this->createQueryBuilder('smth')->addGroupBy('smth.mycolumn');

Symfony3에서 작동 -


정확한 SQL을 사용하지 않은 것에 대한 사과

이 쿼리를 사용하여 Mysql 경고를 극복했습니다.

SELECT count(*) AS cnt, `regions_id`
FROM regionables 
WHERE `regionable_id` = '115' OR `regionable_id` = '714'
GROUP BY `regions_id`
HAVING cnt > 1

나를위한 열쇠에 주목

count(*) AS cnt

참고 : https://stackoverflow.com/questions/34115174/error-related-to-only-full-group-by-when-executing-a-query-in-mysql



반응형