문제

기존 응용 프로그램에 기능을 추가하려고 노력하고 있으며 MySQL보기를 발견했습니다.

SELECT
     AVG(table_name.col1),
     AVG(table_name.col2),
     AVG(table_name.col3),
     table_name.personID,
     table_name.col4
FROM table_name
GROUP BY table_name.personID;

좋아, 몇 가지 집계 기능이 있습니다. 당신은 그것에 의해 그룹화되고 있기 때문에 personID를 선택할 수 있습니다. 그러나 그것은 또한 집계 함수가 아닌 열을 선택하고 있으며 절에 의해 그룹의 일부가 아닙니다. 이것이 어떻게 가능한지??? 그룹당 값이 고유하지 않기 때문에 임의의 값을 선택합니까?

내가 (MSSQL Server)에서 온 곳은 오류입니다. 누군가 나 에게이 행동을 설명하고 왜 MySQL에서 허용되는지 설명 할 수 있습니까?

도움이 되었습니까?

해결책

이 기능이 일부 모호한 쿼리를 허용하고 해당 열에서 선택한 임의의 값으로 결과 세트를 조용히 반환합니다. 실제로, 그것은 먼저 물리적으로 저장된 그룹 내 행의 값 인 경향이 있습니다.

이 쿼리는 기준에 따라 그룹의 열에 기능적으로 의존하는 열만 선택하는 경우 모호하지 않습니다. 다시 말해, 그룹을 정의하는 값 당 "모호한"열의 뚜렷한 값만있을 수 있다면 아무런 문제가 없습니다. 이 쿼리는 Microsoft SQL Server (및 ANSI SQL)에서 불법이지만 논리적으로 모호성을 초래할 수는 없습니다.

SELECT AVG(table1.col1), table1.personID, persons.col4
FROM table1 JOIN persons ON (table1.personID = persons.id)
GROUP BY table1.personID;

또한 MySQL은 표준에 따라 작동하게하는 SQL 모드를 가지고 있습니다. ONLY_FULL_GROUP_BY

fwiw, sqlite는 또한이 모호한 그룹을 조항으로 허용하지만, 그것은 마지막 그룹에서 행.


적어도 내가 테스트 한 버전에서. 그것이 의미하는 바 임의 MySQL 또는 Sqlite는 미래에 구현을 변경하고 다른 동작을 가질 수 있다는 것입니다. 그러므로 당신은 현재 이와 같은 모호한 경우에있는 행동에 의존해서는 안됩니다. 쿼리를 결정 론적이고 모호하지 않도록 다시 작성하는 것이 좋습니다. 그렇기 때문에 MySQL 5.7은 이제 기본적으로 hone_full_group_by를 활성화합니다.

다른 팁

조금만 더 구글을봤을 것입니다 ... 내가 찾은 것 같습니다. 내 대답.

MySQL은 그룹별로 표시되지 않는 선택 목록에서 응집되지 않은 열 또는 계산을 사용할 수 있도록 그룹의 사용을 확장합니다. 불필요한 열 정렬 및 그룹화를 피 함으로써이 기능을 사용하여 더 나은 성능을 얻을 수 있습니다. 예를 들어, 다음 쿼리에서 고객을 그룹화 할 필요가 없습니다.

표준 SQL에서는 Customer.Name을 그룹에 의해 추가해야합니다. MySQL에서는 이름이 중복됩니다.

그래도, 그것은 단지 ... 틀린 것 같습니다.

select * from personel where p_id IN(select
min(dbo.personel.p_id)
FROM
personel
GROUP BY dbo.personel.p_adi)

다음과 같은 쿼리가 있다고 가정 해 봅시다.

SELECT g, v 
FROM t
GROUP BY g;

이 경우, 가능한 각 가능한 값에 대해 g, MySQL은 해당 값 중 하나를 선택합니다 v.

그러나 선택된 것은 어떤 상황에 달려 있습니다.

나는 각 G 그룹에 대해 첫 번째 값을 읽었습니다. v 레코드가 테이블에 어떻게 삽입되었는지 순서대로 유지됩니다. t.

테이블의 기록이 세트 요소의 순서가 중요하지 않은 곳. 이것은 "mysql-ish"입니다 ...

어떤 값을 결정하려면 v 유지하려면 SubSelect를 신청해야합니다. t 이와 같이:

SELECT g, v 
FROM (
    SELECT * 
        FROM t 
        ORDER BY g, v DESC
) q
GROUP BY g;

이렇게하면 하위 쿼리의 레코드가 외부 쿼리에 의해 처리되는 순서를 정의하므로 어떤 값을 신뢰할 수 있습니다. v 개별 값을 선택합니다 g.

그러나 조건이 필요한 경우 매우 조심하십시오. 위치 조건을 하위 쿼리에 추가하면 동작을 유지하면 항상 예상되는 값을 반환합니다.

SELECT g, v 
FROM (
    SELECT * 
        FROM t 
        WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9' 
        ORDER BY g, v DESC
) q
GROUP BY g;

이것이 당신이 기대하는 것, 서브 선택 필터와 테이블을 주문합니다. 그것은 기록을 어디에 보관합니다 g 주어진 값이 있고 외부 쿼리는 다음을 반환합니다. g 그리고 첫 번째 가치 v.

그러나 외부 쿼리에 동일한 위치 조건을 추가하면 결정적이지 않은 결과가 나타납니다.

SELECT g, v 
FROM (
    SELECT * 
        FROM t 
        -- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9' 
        ORDER BY g, v DESC
) q
WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
GROUP BY g;

놀랍게도, 당신은 다른 값을 얻을 수 있습니다 v 같은 쿼리를 계속해서 실행할 때 ... 이상합니다. 예상되는 동작은 하위 쿼리에서 모든 레코드를 적절한 순서로 가져 와서 외부 쿼리에서 필터링 한 다음 이전 예제에서 선택한 것과 동일하게 선택하는 것입니다. 그러나 그렇지 않습니다.

그것은 값을 선택합니다 v 무작위로 겉보기에. 동일한 쿼리가 다른 값을 반환했습니다 v 더 많은 시간 (~ 20)을 실행했지만 분포가 균일하지 않은 경우.

외부를 추가하는 대신 다음과 같은 조건을 지정합니다.

SELECT g, v 
FROM (
    SELECT * 
        FROM t1 
        -- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9' 
        ORDER BY g, v DESC
) q
-- WHERE g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9'
GROUP BY g
HAVING g = '737a8783-110c-447e-b4c2-1cbb7c6b72c9';

그런 다음 다시 일관된 행동을 얻습니다.

결론 : 나는이 기술에 전혀 의존하지 않는 것이 좋습니다. 정말로 원하거나 필요한 경우 외부 쿼리의 조건을 피하십시오. 외부 쿼리에 할 수 있거나 절차가있는 경우 내부 쿼리에 사용하십시오.

이 데이터로 테스트했습니다.

CREATE TABLE t1 (
    v INT,
    g VARCHAR(36)
);

INSERT INTO t1 VALUES (1, '737a8783-110c-447e-b4c2-1cbb7c6b72c9');
INSERT INTO t1 VALUES (2, '737a8783-110c-447e-b4c2-1cbb7c6b72c9');

MySQL 5.6.41에서.

어쩌면 새로운 버전으로 수정 된 버그 일 수도 있습니다. 최신 버전에 대한 경험이있는 경우 피드백을 제공하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top