MySQL - 그룹화 기준 이외의 컬럼 선택
기존 응용 프로그램에 기능을 추가하려고 하는데 다음과 같은 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;
몇 가지 집약 함수가 있습니다.인물을 선택할 수 있습니다.아이디로 분류하고 있기 때문에그러나 집계 함수에 없고 GROUP BY 절의 일부가 아닌 열을 선택합니다.이게 어떻게 가능하죠?값이 그룹별로 고유하지 않기 때문에 무작위로 값을 선택하는 것일까요?
(MSSQL Server)는 에러입니다.누가 이 동작과 MySQL에서 허용되는 이유를 설명해 줄 수 있나요?
이 기능은 일부 모호한 쿼리를 허용하고 해당 열에서 선택한 임의 값을 사용하여 결과 집합을 자동으로 반환합니다.실제로 가장 먼저 물리적으로 저장되는 것은 그룹 내 행의 값인 경향이 있습니다.
이러한 쿼리는 GROUP BY 기준의 열에 따라 기능적으로 종속된 열만 선택하는 경우 모호하지 않습니다.즉, 그룹을 정의하는 값당 "모호한" 열의 고유한 값이 하나만 있으면 문제가 없습니다.이 쿼리는 논리적으로 애매한 결과를 가져올 수 없지만 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 모드가 있어 표준에 따라 동작합니다.
FWIW, SQLite에서는 이러한 애매한 GROUP BY 구도 허용되지만 그룹 †내 마지막 행에서 값이 선택됩니다.
† 적어도 내가 테스트한 버전에서는.즉, MySQL 또는 SQLite 중 하나의 구현이 미래에 변경되어 동작이 달라질 수 있습니다.따라서 당신은 현재와 같이 애매한 경우에 머물러 있는 행동에 의존해서는 안 된다.쿼리를 애매모호하지 않고 확정적으로 다시 쓰는 것이 좋습니다.그렇기 때문에 MySQL 5.7에서는 기본적으로 ONLY_FULL_GROUP_BY만 사용할 수 있게 되었습니다.
조금만 더 검색해봤어야 했는데...답을 찾은 것 같아요.
MySQL은 GROUP BY 절에 표시되지 않는 SELECT 목록의 비집약 열 또는 계산을 사용할 수 있도록 GROUP BY의 사용을 확장합니다.이 기능을 사용하면 불필요한 열 정렬 및 그룹화를 방지하여 성능을 향상시킬 수 있습니다.예를 들어, 다음 쿼리에서는 customer.name에서 그룹화할 필요가 없습니다.
표준 SQL에서는 GROUP BY 절에 customer.name을 추가해야 합니다.MySQL에서는 이름이 중복됩니다.
그래도, 그건 그냥...틀렸어.
예를 들어 다음과 같은 질문이 있다고 가정합니다.
SELECT g, v
FROM t
GROUP BY g;
「 」의 각 에 대해서, 「 」는 「 」g
하는 mysql 값 중 v
.
그러나 어떤 것이 선택될지는 상황에 따라 다릅니다.
선가 읽은 로 g의 첫 값, g의 첫 번째 입니다.v
보관됩니다.t
테이블 내의 레코드는 요소의 순서가 중요하지 않은 세트로 취급해야 하기 때문에 이것은 매우 보기 흉합니다.이건 정말 "mysql-ish"...
「」의 어느 .v
하려면 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,t
음음음같 뭇매하다
SELECT g, v
FROM (
SELECT *
FROM t
ORDER BY g, v DESC
) q
GROUP BY g;
외부 쿼리에 할 수 어떤 이 처리되는지 할 수 .따라서 다음 값인지 신뢰할 수 있습니다.v
.g
그러나 WHERE 조건이 필요한 경우 매우 주의해야 합니다.WHERE 조건을 서브쿼리에 추가하면 동작이 유지되고 항상 예상되는 값이 반환됩니다.
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
그러나 외부 쿼리에 동일한 WHERE 조건을 추가하면 비결정적 결과가 나타납니다.
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
모든 를 적절한 순서로 후 입니다.예상되는 동작은 서브쿼리에서 적절한 순서로 모든 레코드를 가져와 외부 쿼리에서 필터링한 후 이전 예에서 선택한 것과 동일한 레코드를 선택하는 것입니다.하지만 그렇지 않다.
it을 for for for for for for for for 의 값을 고릅니다.v
무작위로 보입니다.에서 다른 되었습니다.v
20회 이상 실행했지만 배포가 균일하지 않은 경우.
외부 WHERE를 추가하는 대신 HAVING 조건을 다음과 같이 지정하는 경우:
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';
그러면 다시 일관된 행동을 하게 됩니다.
결론: 저는 이 기술에 전혀 의존하지 말 것을 제안합니다.외부 쿼리에서 WHERE 조건을 반드시 피해야 합니다.가능한 경우 내부 쿼리에서 또는 외부 쿼리에 HAVING 절을 사용합니다.
다음 데이터로 테스트했습니다.
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로 지정합니다.
새로운 버전에서 수정/수정된 버그일 수도 있으니 새로운 버전을 사용해 본 경험이 있다면 피드백을 주세요.
select * from personel where p_id IN(select
min(dbo.personel.p_id)
FROM
personel
GROUP BY dbo.personel.p_adi)
언급URL : https://stackoverflow.com/questions/1023347/mysql-selecting-a-column-not-in-group-by
'source' 카테고리의 다른 글
조타 도표에서 /docker-entrypoint-initdb.d에 액세스하는 방법 (0) | 2023.01.15 |
---|---|
PyCrypto AES 256을 사용한 암호화 및 복호화 (0) | 2023.01.15 |
리소스 컨트롤러의 Larabel 명명된 경로 (0) | 2023.01.15 |
GDB를 사용하여 메모리 내용을 수정하는 방법 (0) | 2023.01.15 |
재귀 SQL 쿼리의 무한 루프 (0) | 2023.01.15 |