2010-12-02 4 views
1
나는 세 개의 테이블의 총을 통해 가입하려고 문제가 오전

:INNER는 SUM 3 개 테이블()에 가입

  • 표 사용자 : 사용자 ID, 모자 (ADSL 대역폭)
  • 표 회계 : 사용자 ID를 , SESSIONDATE, 사용 대역폭
  • 표 애드혹 : 사용자 ID, 날짜, 금액은

내가 모든 사용자가 자신의 모자, 이번 달 자신의 사용 대역폭과 애드혹 구매의 집합을 반환 한 쿼리를 갖고 싶어 구입 이 몽 H : 여기

< TABLE 1 ><TABLE2><TABLE3> 
User | Cap | Adhoc | Used 
marius | 3 | 1  | 3.34 
bob | 1 | 2  | 1.15 
(simplified) 

내가 작업하고있는 쿼리입니다 :

SELECT 
     `msi_adsl`.`id`, 
     `msi_adsl`.`username`, 
     `msi_adsl`.`realm`, 
     `msi_adsl`.`cap_size` AS cap, 
     SUM(`adsl_adhoc`.`value`) AS adhoc, 
     SUM(`radacct`.`AcctInputOctets` + `radacct`.`AcctOutputOctets`) AS used 
FROM 
     `msi_adsl` 
INNER JOIN 
     (`radacct`, `adsl_adhoc`) 
ON 
     (CONCAT(`msi_adsl`.`username`,'@',`msi_adsl`.`realm`) 
      = `radacct`.`UserName` AND `msi_adsl`.`id`=`adsl_adhoc`.`id`) 

WHERE 
     `canceled` = '0000-00-00' 
AND 
     `radacct`.`AcctStartTime` 
BETWEEN 
     '2010-11-01' 
AND 
     '2010-11-31' 
AND 
     `adsl_adhoc`.`time` 
BETWEEN 
     '2010-11-01 00:00:00' 
AND 
     '2010-11-31 00:00:00' 
GROUP BY 
     `radacct`.`UserName`, `adsl_adhoc`.`id` LIMIT 10 

쿼리가 작동하지만, 애드혹 및 사용 모두에 대해 잘못된 값을 반환; 내 추측은 내 조인에 논리적 오류가 될 수 있지만 그것을 볼 수 없습니다. 어떤 도움이라도 대단히 감사합니다.

+0

감사를 그런 식으로 더 나은 태그의 ajreal을, 편집) – Marius

+0

을 문제의 테이블 이름과 일치하지 않는 쿼리의 테이블 이름; 영역은 쿼리에는 나타나지만 테이블에는 나타나지 않습니다. –

+0

예 실제 질문과 비교하여 질문을 단순화했습니다. username은 username @ realm의 조합이며 하나의 테이블은 이들을 분리하고 다른 테이블에는 하나의 필드가 있습니다. – Marius

답변

3

검색어 레이아웃이 너무 미미합니다. 특히 BETWEEN/AND 조건은 각각 5 줄이 아니라 1 줄로해야합니다. 나는 '시간'열에 그들을 필요로 할지도 모르지만, backticks도 제거했습니다.

테이블 레이아웃이 샘플 쿼리와 일치하지 않으므로 작업이 매우 어려워집니다. 그러나 테이블 레이아웃에는 모두 UserID가 포함되어 있으므로 UserID를 사용하여 관련 조인을 수행하는 쿼리를 작성했습니다. 의견에서 언급했듯이, 설계로 인해 CONCAT 연산을 사용하여 두 테이블을 조인해야하는 경우 성능 재앙을위한 처방이 있습니다. 테이블 레이아웃 제안이 가능해야하므로 실제 스키마를 업데이트하여 UserID로 테이블을 조인 할 수 있습니다. 분명히 함수 결과를 조인으로 사용할 수는 있지만 DBMS가 '기능적 인덱스'를 지원하고 적절한 인덱스를 작성하지 않는 한 DBMS는 쿼리 속도를 높이기 위해 함수가 평가 된 테이블의 인덱스를 사용할 수 없습니다. 일회성 쿼리의 경우에는 중요하지 않을 수 있습니다. 프로덕션 쿼리의 경우 종종 중요합니다.

원하는 작업을 수행 할 수있는 기회가 있습니다. 두 테이블 이상을 집계하기 때문에 FROM 절에 두 개의 하위 쿼리가 필요합니다.

SELECT u.UserID, 
     u.username, 
     u.realm, 
     u.cap_size AS cap, 
     h.AdHoc, 
     a.OctetsUsed 
    FROM msi_adsl AS u 
    JOIN (SELECT UserID, SUM(AcctInputOctets + AcctOutputOctets) AS OctetsUsed 
      FROM radact 
     WHERE AcctStartTime BETWEEN '2010-11-01' AND '2010-11-31' 
     GROUP BY UserID 
     ) AS a ON a.UserID = u.UserID 
    JOIN (SELECT UserID, SUM(Value) AS AdHoc 
      FROM adsl_adhoc 
     WHERE time BETWEEN '2010-11-01 00:00:00' AND '2010-11-31 00:00:00' 
     GROUP BY UserId 
     ) AS h ON h.UserID = u.UserID 
WHERE u.canceled = '0000-00-00' 
LIMIT 10 

각 서브 쿼리 ID와 출력 열로 합계 값을 생성하고, 특정 기간 동안의 각 사용자에 대한 집합의 값을 계산한다; 기본 쿼리는 주 사용자 테이블에서 올바른 사용자 데이터를 가져 와서 집계 하위 쿼리와 조인합니다.

+0

안녕하세요, 조나단, 아주 잘 생겼습니다. 지금 시험해보고 다시 돌아 오게됩니다. – Marius

+0

안녕하세요, 조나단, 대단히 고마워요. – Marius

+0

@Jonathan Leffler 질문에 4 시간 이상 머물렀고 귀하의 게시물이 나를 많이 도왔습니다 !! +1이 :) – Kamran

0

나는 문제가 여기에 당신이 혼합되어

FROM `msi_adsl` 
INNER JOIN 
     (`radacct`, `adsl_adhoc`) 
ON 
     (CONCAT(`msi_adsl`.`username`,'@',`msi_adsl`.`realm`) 
      = `radacct`.`UserName` AND `msi_adsl`.`id`=`adsl_adhoc`.`id`) 

직교 제품에 결합하고, 디버그에 많이 힘들어 때문에 이것은 좋은 생각이 아니라고 생각합니다. 이 시도 :

FROM `msi_adsl` 
INNER JOIN 
     `radacct` 
ON 
     CONCAT(`msi_adsl`.`username`,'@',`msi_adsl`.`realm`) = `radacct`.`UserName` 
JOIN `adsl_adhoc` ON `msi_adsl`.`id`=`adsl_adhoc`.`id`