2009-03-18 6 views
15

두 개의 쿼리가 있습니다. 그들 중 하나는 나에게 의미가 있고, 다른 하나는 그렇지 않습니다. 하나의 제 :MySQL : 총 GROUP BY WITH ROLLUP 호기심

SELECT gender AS 'Gender', count(*) AS '#' 
    FROM registrations 
    GROUP BY gender WITH ROLLUP 
이 나 있습니다

:

Gender  # 
Female  20 
Male  19 
NULL  39 

그래서, 나는 저에게 수를, 그리고 총 수입니다. 내가 기대했던 것. 다음 :

SELECT c.printable_name AS 'Country', count(*) AS '#' 
    FROM registrations r 
    INNER JOIN country c ON r.country = c.country_id 
    GROUP BY country WITH ROLLUP 

Country   # 
Denmark   9 
Norway   10 
Sweden   18 
United States 1 
Uzbekistan  1 
Uzbekistan  39 

같은 결과입니다. 그런데 왜 나는 우즈베키스탄을 총으로 얻는가 ??

+0

결과가 어떻게 표시되지 않는 것이 확실합니까? –

+0

내 코드와 phpmyadmin에서 모두 발생합니다. 내가 정기적으로 MySQL의 쿼리 브라우저 또는 무언가로 그것을 테스트하려고 할 수 있지만 액세스 권한이 없어. – Svish

+0

전 롤업으로 놀고 있었어요. 여기서 문제는 나라 ID에 국가 ID를 합치면 모든 NULL 값이 조인을하지 않으며 이름이없는 대신 이름의 마지막 값을 유지한다는 것입니다. – sphism

답변

36

하지만 왜 내가 총 우즈 베키스탄받을 수 있나요 ?? : 여기 내 제안이다

GROUP BY BY 항목을 선택하지 않았기 때문에. 당신이 말한 경우 :

GROUP BY c.printable_name 

당신은 예상되는 NULL을 얻을 것입니다. 그러나 MySQL이 printable_name이 롤업 그룹에 참여하고 있는지 알지 못하도록 다른 컬럼별로 그룹화하고 있습니다. 모두 등록에서이 컬럼의 이전 값을 선택합니다. (따라서 우즈베키스탄 이외의 나라도보실 수 있습니다.)

이것은 GROUP BY 쿼리에서 SELECT 할 수있는 MySQL에 대한 더 광범위한 문제 중 일부입니다.

SELECT gender FROM registrations GROUP BY country; 

및 MySQL은 행복하게 국가 및 성별 사이에 직접적인 인과 관계 (일명 "기능 종속성")이없는 경우에도, 각 국가에서 등록 성별 값 중 하나를 선택합니다 : 예를 들어, 당신은 말할 수 . 다른 DBMS를 국가 당 하나 개의 성이있을 보장되지 않는다는 이유로 위의 명령을 거부합니다 (*)

을 자,이 :.

SELECT c.printable_name AS 'Country', count(*) AS '#' 
FROM registrations r 
INNER JOIN country c ON r.country = c.country_id 
GROUP BY country 

확인하고, 함수 적 종속성 사이가 있기 때문에 r.country 및 c.printable_name (country_id를 PRIMARY KEY로 정확하게 설명했다면).

그러나 MySQL의 WITH ROLLUP 확장은 작동 방식에 대한 약간의 해킹입니다. 끝에있는 롤업 행 단계에서 그룹 전체의 결과 집합을 실행하여 값을 가져오고 다음은 그룹화 열을 NULL로 설정합니다. 해당 열에 기능적 종속성이있는 다른 열도 null로 지정하지 않습니다. 아마도 그렇 겠지만, MySQL은 현재 기능 의존성에 대해 모든 것을 정말로 이해하지 못하고 있습니다.

그래서 c.printable_name을 선택하면 무작위로 선택한 국가 이름 값이 표시되고 c를 선택하면 c.printable_name이 선택됩니다.country_id - c.country_id가 조인 기준 임에도 불구하고 무작위로 선택한 국가 ID를 표시하므로 r.country와 동일해야합니다. 이는 NULL입니다!

당신이 문제를 해결하기 위해 할 수있는 것은 :

  • 그룹 대신 printable_name에 의해; printable_names가 유일 할 경우
  • "r.country"와 printable_name을 선택하고 NULL이 맞는지 확인하거나
  • WITH ROLLUP을 잊어 버리고 최종 합계에 대해 별도의 쿼리를 수행하십시오. 조금 느려지 겠지만 ANSI SQL-92를 준수하므로 앱이 다른 데이터베이스에서도 작동 할 수 있습니다.

(* : MySQL은이 문제를 해결하기로하는 SQL_MODE 옵션 ONLY_FULL_GROUP_BY을 가지고 있지만 너무 멀리 가고 만이 그룹에 기능 의존성이있는 GROUP BY의 열이 아닌 열을 선택할 수 있습니다 그것을 만들 것입니다 그래서 BY. 유효한 쿼리는 '총 등록 = 39'

+0

+1 굉장한 정보 – diEcho

0

Coz JOIN 메서드를 사용할 때 다음 배열의 NULL 요소에는 이전 NOT NULL 요소 값이 있습니다. 그러나 확실하지 않은 Im. PHP로 사용할 때 내 경험이 그 것이다.

흠 ... 또 하나의 문제가 있습니다 ... '나라'는 테이블이므로 '깡통'입니다. 그래서 다른 것을 위해 변화하십시오. 그런 다음 마지막 결과는 NULL을 표시합니다.

$result = mysql_query("SELECT c.printable_name AS 'countryp', count(*) AS '#' 
FROM registrations r, country c WHERE r.country = c.country_id 
GROUP BY countryp WITH ROLLUP"); 

while($row = @mysql_fetch_array($result)) { 
    $r1 = $row["countryp"]; 
    $r2 = $row["#"]; 
    if ($r1 == NULL) $r1 = 'Total'; 
    echo "$r1 $r2<br />"; 
} 
+0

같은 방식으로 작동하도록 쿼리를 조정할 수 있지만 다른 것과 같이 전체적인 것으로 NULL을 사용할 수 있습니까? – Svish

+0

이것은 이상한 ... 나는 이것을 얻지 않는다, 하하. 그래서 나는 'countryp'와 GROUP BY countryp를 사용할 때 작동합니다. 'name'을 사용하면 그렇지 않습니다. 'qe'를 사용하면 ... – Svish

0
SELECT ifnull(c.printable_name, "Total Registration = ") AS 'Country', count(*) AS '#' 
FROM registrations r 
INNER JOIN country c ON r.country = c.country_id 
GROUP BY country WITH ROLLUP; 

이 인쇄 것이다). 그것은 일반적으로 쓸모 만들기,뿐만 아니라 실패하고 마지막 행/기록 될 것입니다.