2013-08-13 5 views
2

합계 필드 값이 이고 다른 값은 필드 값입니다. 이 used_points 또는 added_points 그리고 AS used_points/added_points에 넣어 경우다른 열 값에 따라 열 합계

나는 activities.activity_type에 따라 SUM(activities.points)해야합니다.

활동 :

id | subscription_id | activity_type | points 
-------------------------------------------------- 
1 |   1  | used_points | 10 
2 |   1  | used_points | 50 
3 |   1  | added_points | 20 
4 |   1  | added_points | 30 
5 |   2  | used_points | 20 
6 |   2  | used_points | 45 
7 |   2  | added_points | 45 
8 |   2  | added_points | 45 

구독 :

id |  name | current_points 
------------------------------------- 
1 | card_1 |  700 
2 | card_2 |  900 

내가 필요로하는 무엇을 : 나는 시도 무엇

name | current_points | used_points | added_points 
----------------------------------------------------------- 
card_1 |   700  |  60  |  50 
card_2 |   900  |  65  |  90 

:

SELECT 
    subscriptions.name, 
    subscriptions.current_points, 
    IF(activities.activity_type="used_points", SUM(activities.points), null) 
     AS used_points, 
    IF(activities.activity_type="added_points", SUM(activities.points), null) 
     AS added_points 
FROM activities 
JOIN subscriptions 
    ON activities.subscription.id = subscription.id 
GROUP BY subscriptions.name 

잘못된 것입니다.

감사는 열과 합계 사항을 확인하거나 0

+0

**'SUM (IF())'**를 사용하고 싶습니다. 즉,'IF' 표현식 안에서'SUM' 집계 함수를 제거하고'IF' 표현식을'SUM'에 랩핑하십시오. IF 표현식은 개별 행에 대해 작동해야하며, SUM은 각 행에 대해 리턴 된 값을 집계합니다. – spencer7593

답변

3

당신은 SUM(IF())를 사용하려면이 방법으로 다음

SUM(IF(activities.activity_type="used_points", activities.points, 0)) 
    AS used_points, 
SUM(IF(activities.activity_type="added_points", activities.points, 0)) 
    AS added_points 

으로

+0

예, 이것이 효과가있는 것 같습니다. 하지만'IF '내부의'SUM()'이 작동하지 않는 이유는 무엇입니까? – Vucko

+0

SUM은 함께 집계 된 모든 행에 대해 평가되고 단일 값을 반환합니다. IF 내부에 있다면, IF 함수는 SUM 함수에 의해 반환 된 하나의 값에 대해서 단 한 번만 계산됩니다. 다른 데이터베이스는 IF의 다른 표현식이 집계가 아니기 때문에 SQL 문과 함게 오류를 던집니다. MySQL은 좀 더 관대하며 SUM 집계에 포함 된 모든 행에서 단일 행을 선택하고 샘플 행의 값을 집계로 사용합니다. – spencer7593

+0

자세한 답변을 보내 주셔서 감사합니다. – Vucko

1

보십시오 변화

IF(activities.activity_type="used_points", null, SUM(activities.points)) 
    AS used_points, 
IF(activities.activity_type="added_points", null, SUM(activities.points)) 
    AS added_points 

. IF에서 반환 된 값을 합산하려고합니다. 각 행에 대해 IF 표현식을 계산하기를 원합니다. 그런 다음 SUM 집합을 사용하여 각 행에 대해 반환 된 값을 더합니다.

IF 표현식에서 SUM 집합체를 제거하고 대신 IFSUM 안에 넣습니다. IF의 내부 SUM()가 작동하지 않습니다


후속 조사

Q 왜?

글쎄요. 원하는대로 작동하지 않습니다.

MySQL SUM 함수는 "집계"함수입니다. 행을 함께 집계하고 단일 값을 반환합니다. 이 양식의 표현에 대한

: IF(col='foo',SUM(numcol),0)

무엇 MySQL의이 SUM에 모든 행을 집계되어 일을하고, 단일 값을 반환합니다.

다른 데이터베이스는 적합을 피하고 그 표현식에 집합이 아닌 col에 대한 참조와 함께 오류를 발생시킵니다.MySQL은 좀 더 관대하고 col 참조를 마치 MIN (col) 또는 MAX (col)와 같은 집계로 처리하여 행 그룹에서 작업하고 단일 값을 반환합니다.이 경우 MySQL은 하나의 샘플 행 (어떤 행이 샘플 행으로 "선택"될지는 결정하지 않습니다.) 따라서 col에 대한 참조는 GET_VALUE_FROM_SAMPLE_ROW(col)과 비슷합니다. 집계가 완료되면 IF식이 한 번 계산됩니다 ..

이 쿼리를 시작하면

, 이것은 당신이 조작하려는 행의 집합입니다.

SELECT s.name 
    , s.current_points 
    , a.activity_type 
    , a.points 
    , IF(a.activity_type='used_points',a.points,NULL) AS used_points 
    , IF(a.activity_type='added_points',a.points,NULL) AS added_points 
    FROM subscriptions s 
    JOIN activities a 
    ON a.subscription_id = s.id 

당신이 GROUP BY 절을 추가

, 즉 함께 해당 행의 일부를 통합 할 것입니다. 비 집계를 위해 얻을 수있는 것은 샘플 행의 값입니다.

GROUP BY s.name을 쿼리에 추가하여 반환되는 내용을 확인하십시오.

또한 (a.points) 마지막으로

SELECT s.name 
    , s.current_points 
    , a.activity_type 
    , a.points 
    , IF(a.activity_type='used_points',a.points,NULL) AS used_points 
    , IF(a.activity_type='added_points',a.points,NULL) AS added_points 
    , SUM(a.points) AS total_points 
    FROM subscriptions s 
    JOIN activities a 
    ON a.subscription_id = s.id 
GROUP BY s.name 

, 우리는 SELECT 목록에 검색어의 표현에 추가 할 수 있습니다 SUM과 같은 일부 집계에 추가하려고 :

 , IF(a.activty_type='used_points',SUM(a.points),NULL) AS if_used_sum 
    , IF(a.activty_type='added_points',SUM(a.points),NULL) AS if_added_sum 

무엇 이 표현식에서 반환 된 값은 total_points과 일치하는 SUM (a.points)이거나 NULL 일 것입니다. 그리고 각 그룹에 대해 단일 샘플 행에서 검색 한 activity_type 열의 값을 볼 수 있습니다.이 값이 "작동 중"이라는 것을 알 수 있습니다. 실제로 원하는 것을 수행하지 않습니다. 조건부 각각의 개별 행에서 실행되도록 테스트하고, 포인트 또는 null에 대한 값을 반환 한 다음 그룹에 대해 합산합니다.

+2

@BenC. 이 질문은 SQL Server가 아닌 MySQL에 관한 것입니다. –

+0

그렇습니다. 내 의견을 삭제하겠습니다. –

1

코드는 약간 밖으로 :

SELECT 
    subscriptions.name, 
    subscriptions.current_points, 
    SUM(IF(activities.activity_type="used_points", 0, activities.points)) 
     AS used_points, 
    SUM(IF(activities.activity_type="added_points", 0, activities.points)) 
     AS added_points 
FROM activities 
JOIN subscriptions 
    ON activities.subscription_id = subscription.id 
GROUP BY subscriptions.name, subscriptions.current_points 

참고가 두 번째 마지막 줄에 고정 오타가 - 대신 subscription_id의 subscription.id 썼다. 또한 이름과 current_points 대신 이름으로 만 그룹화했습니다. mysql (T-SQL 사용)에서 허용되는지 확실하지 않으므로 어쨌든 거기에있는 것이 좋습니다.

1

글쎄, 나는 IF 문을 사용하지 않았다. 여기에 예 (http://sqlfiddle.com/#!2/076c3f/12는)입니다 :

SELECT 
    subs.name, 
    subs.current_points, 
    (SELECT SUM(points) FROM activities WHERE type = 1 AND subs_id = subs.id) AS used_points, 
    (SELECT SUM(points) FROM activities WHERE type = 2 AND subs_id = subs.id) AS added_points 
FROM activities 
JOIN subs ON activities.id = subs.id 
GROUP BY subs.name 

참고 : 나는 단순화하기 위해 int로 VARCHAR에서 유형을 변경했습니다.

+1

지정한 결과 집합은 예제에 표시된 것처럼 상관 된 하위 쿼리를 사용하여 얻을 수 있습니다. 그러나 상관 관계가있는 서브 쿼리는 대개 다른 대안 (많은 수의 행)보다 효율성이 떨어집니다. 하나의 대안은 SELECT 목록에서 표현식'SUM (IF (type = 1, points, 0)) AS used_points'를 사용하는 것입니다. 하위 쿼리는 사용하지 않습니다. – spencer7593

+0

나는 본다. 설명 해줘서 고마워. 나는 대안의 효용을 주요 요인으로 생각하지 않았습니다. 효율성이 얼마나 좋은지 확인하려고 노력할 것입니다. – Minoru

+1

테이블 ** activities **에 대해 64 개의 행이있는 경우 _ 관련 하위 쿼리의 평균 시간은 약 5ms이고 _IF expression_을 사용하는 평균 시간은 1ms입니다 (아마도 엔진은 부동 소수점을 사용하지 않지만 시간 동안). – Minoru