2009-06-21 6 views
35

에 의해 그룹에서가 아니라 열 선택이 같은 MySQL의보기 뭔가를 가로 질러왔다. personID는 그룹으로 그룹화했기 때문에 선택할 수 있습니다. 그러나 또한 집계 함수에없고 GROUP BY 절의 일부가 아닌 열을 선택하고 있습니다. 이것이 어떻게 가능한지??? 값이 그룹마다 고유하지 않기 때문에 임의의 값을 선택합니까?MySQL은 내가 기존 응용 프로그램에 기능을 추가하기 위해 노력하고있어

내가 (MSSQL 서버)에서 왔는데 오류입니다. 누군가가이 동작을 내게 설명 할 수 있고 MySQL에서 허용되는 이유는 무엇입니까?

답변

40

이 기능은 모호한 쿼리를 허용하고 해당 열에서 임의의 값을 선택하여 결과 집합을 자동으로 반환합니다. 실제로는 그룹 내에서 물리적으로 먼저 저장된 행의 값인 경향이 있습니다.

GROUP BY 조건의 열에 기능적으로 종속 된 열만 선택하면 이러한 쿼리가 모호하지 않습니다. 즉, 그룹을 정의하는 값마다 "모호한"열의 고유 한 값만있을 수 있으면 아무런 문제가 없습니다. 이 쿼리는 논리적 모호성을 초래할 수 없지만, 마이크로 소프트 SQL 서버 (및 ANSI의 SQL)에서 불법 것 : ONLY_FULL_GROUP_BY

: 또한

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

, MySQL은이 표준에 따라 행동 할 수있는 SQL 모드가 있습니다

FWIW, SQLite는 또한이 모호한 GROUP BY 절을 허용하지만 그룹의 마지막 행의 값을 선택합니다. 이상 버전에서 내가 테스트


†. 무슨 임의의 될 것을 의미하는 MySQL 또는 SQLite 향후 구현을 변경할 수 있으며 일부 다른 동작이 있습니다. 따라서 현재 이와 같은 모호한 상황에있는 것처럼 행동에 의존해서는 안됩니다. 결정을 명확하게하고 애매하지 않도록 쿼리를 다시 작성하는 것이 좋습니다. 이것이 MySQL 5.7이 기본적으로 ONLY_FULL_GROUP_BY를 활성화하는 이유입니다.

+3

저는 이것이 완전히 사실이 아니라고 말하고 싶습니다. ANSI SQL-99에서 선택된 필드는 집계이어야하며, 기능은 group by 절에 따라 다릅니다. user_id로 그룹화 할 때 user_name을 선택하면됩니다. SQL Server와 Oracle은 user_id가 group by list에있을 때 user_name을 선택하지 못하도록하기 때문에이를 준수하지 않습니다. MySQL은 실제로 선택된 컬럼이 실제로 user_id에 기능상으로 종속되어 있는지 여부를 확인하지 않기 때문에이를 준수하지 않습니다. –

+0

@ThorstenKettner, 고맙습니다. 당신 말이 맞습니다. MySQL 5.7이 개선되었으며 ANSI SQL을 지원하는 경우 훨씬 더 지능적입니다. –

9

나는 조금 더 길게 인터넷 검색을해야만했다 ... 나는 my answer을 찾은 것 같다.

는 MySQL은 당신이 GROUP BY 절에 나타나지 않는 SELECT 목록 에 집계되지 열 또는 계산을 사용할 수 있도록 BY GROUP의 사용을 확장합니다. 이 기능을 사용하면 불필요한 열 정렬과 그룹화를 피함으로써 더 나은 성능을 얻을 수 있습니다. 예를 들어, 표준 SQL 쿼리

다음 에서 customer.name에 그룹에 필요하지 않습니다, 당신은 GROUP BY 절에 customer.name를 추가해야합니다. MySQL에서는 이름이 중복됩니다.

그래도 그건 ... 잘못된 것 같습니다.

+3

네가 맞을 것 같아. 그것은! 위의 Bill Karwin이 지적한 바와 같이 일부 예외 사례가 있다고 확신하지만 너무 자주 데이터를 잘 모르는 개발자 나이 기능이 실제로 어떻게 작동 하는지를 부적절한 그룹 별 절로 작성합니다. 나쁜 결과를 얻을 수 있습니다. 이 기능은 기본적으로 해제되어 있어야하며 엔지니어가이를 충분히 사용할 수 있다고 알리는 경우 사용할 수 있도록 쿼리 옵션으로 고의로 무시할 수 있어야합니다. –

+0

'SELECT * FROM table1'이 주어진 일관된 순서로 결과를 반환하는 것보다 더 이상 "잘못"하지 않습니다 : 그것은 버그가 아니라 기능입니다. – kmoser

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

이것은 확실히 질문에 답하지 않습니다. – Ojen

+0

@Ojen 그렇지 않습니다.하지만 무슨 일이 일어나고 있는지 설명하고 있습니다. 위의 코드는이 비표준 동작을 표준 SQL을 사용하여 모델링하는 방법의 예입니다. – Griddo

관련 문제