복붙노트

[SQL] GROUP BY + CASE 문

SQL

GROUP BY + CASE 문

나는 하드웨어 모델과 결과에 의해 데이터를 그룹화하는 작업 쿼리를 가지고 있지만 문제는 많은 "결과"가있다. 나는 "1 결과 = 0 다음 0으로 유지하는 경우, 다른 세트는"해당 아래를 줄이기 위해 노력했다. 이것은 일반적으로 작동하지만 내가 가진 결국 :

    day     |      name      | type | case | count
------------+----------------+------+------+-------
 2013-11-06 | modelA         |    1 |    0 |   972
 2013-11-06 | modelA         |    1 |    1 |    42
 2013-11-06 | modelA         |    1 |    1 |     2
 2013-11-06 | modelA         |    1 |    1 |    11
 2013-11-06 | modelB         |    1 |    0 |   456
 2013-11-06 | modelB         |    1 |    1 |    16
 2013-11-06 | modelB         |    1 |    1 |     8
 2013-11-06 | modelB         |    3 |    0 | 21518
 2013-11-06 | modelB         |    3 |    1 |     5
 2013-11-06 | modelB         |    3 |    1 |     7
 2013-11-06 | modelB         |    3 |    1 |   563

대신에 내가 달성하기 위해 노력하고 집계의 경우 유형 / 케이스 콤보 당 1 행입니다.

    day     |      name      | type | case | count
------------+----------------+------+------+-------
 2013-11-06 | modelA         |    1 |    0 |   972
 2013-11-06 | modelA         |    1 |    1 |    55
 2013-11-06 | modelB         |    1 |    0 |   456
 2013-11-06 | modelB         |    1 |    1 |    24
 2013-11-06 | modelB         |    3 |    0 | 21518
 2013-11-06 | modelB         |    3 |    1 |   575

여기 내 쿼리는 다음과 같습니다

select CURRENT_DATE-1 AS day, model.name, attempt.type, 
       CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END, 
       count(*) 
from attempt attempt, prod_hw_id prod_hw_id, model model
where time >= '2013-11-06 00:00:00'  
AND time < '2013-11-07 00:00:00'
AND attempt.hard_id = prod_hw_id.hard_id
AND prod_hw_id.model_id = model.model_id
group by model.name, attempt.type, attempt.result
order by model.name, attempt.type, attempt.result;

내가 이것을 달성 할 수있는 방법에 대한 팁 좋지 않을까.

이 변화하지 않도록 날은 항상 WHERE 절에 정의됩니다. 이름, 유형, 결과 (케이스)와 수는 달라질 수 있습니다. 즉, 특정 모델에 나는 "+ 케이스를 입력"콤보 당 1 행을 원한다. 첫 번째 결과 집합에서 볼 수 있듯이 내가 유형 = 1 케이스 = 1이 MODELA 3 개 행이 (많은 "결과"값이 있기 때문에 나는 0 = 0으로 바뀌 었는지, 그리고 무엇 = 1). I는 2 설정 예로서 데이터 집계 카운트 1 행으로 표현하고자.

해결법

  1. ==============================

    1.귀하의 질의는 이미 작동합니다 - 당신이 이름 충돌로 실행하거나 다른 내용이 소스 열 결과로 출력 열 (CASE 표현식)을 혼동된다는 점을 제외하고.

    귀하의 질의는 이미 작동합니다 - 당신이 이름 충돌로 실행하거나 다른 내용이 소스 열 결과로 출력 열 (CASE 표현식)을 혼동된다는 점을 제외하고.

    ...
    GROUP BY model.name, attempt.type, attempt.result
    ...

    대신 소스 컬럼의 당신의 CASE 표현식 GROUP 필요 :

    ...
    GROUP BY model.name, attempt.type
           , CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END
    ...

    또는 목록에서의 모든 열 이름에서 다르다 열 별칭을 제공합니다 - 그렇지 않으면 열은 우선합니다 :

    SELECT ...
         , CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END AS result1
    ...
    GROUP BY model.name, attempt.type, result1
    ...

    표준 SQL이 점에서 다소 특이하다. 여기 설명서를 인용 :

    과:

    굵게 강조 광산.

    이러한 충돌은 왼쪽에서 오른쪽으로 SELECT 목록의 항목을 참조, GROUP BY와 ORDER BY에 위치 참조 (서수)를 사용하여 피할 수 있습니다. 아래의 솔루션을 참조하십시오. 단점은이 (하나를 따라 위치 참조를 적용하는 것을 잊지 수) 열심히 읽고 SELECT 목록에서 편집에 취약 할 수 있다는 것이다.

    그러나 당신은 그것이 상수 값 (CURRENT_DATE-1) 보유로, GROUP BY 절에 열 일을 추가 할 필요가 없습니다.

    재 작성하고 적절한 단순화는 구문과는 같이 할 수 위치 참조를 가입 :

    SELECT m.name
         , a.type
         , CASE WHEN a.result = 0 THEN 0 ELSE 1 END AS result
         , CURRENT_DATE - 1 AS day
         , count(*) AS ct
    FROM   attempt    a
    JOIN   prod_hw_id p USING (hard_id)
    JOIN   model      m USING (model_id)
    WHERE  ts >= '2013-11-06 00:00:00'  
    AND    ts <  '2013-11-07 00:00:00'
    GROUP  BY 1,2,3
    ORDER  BY 1,2,3;

    또한 내가 열 이름 시간을 방지하고 있습니다. 즉 예약어이고 식별자로 사용해서는 안됩니다. 그 오히려 오해의 소지가 그래서 게다가, 당신의 "시간"분명히 타임 스탬프 또는 날짜이다.

  2. ==============================

    2.당신이 이것을 시도하십시오 수 있습니다 : 아래 하나의 경우 문을 교체

    당신이 이것을 시도하십시오 수 있습니다 : 아래 하나의 경우 문을 교체

    Sum(CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END) as Count,
    
  3. ==============================

    3.그룹이에 다른 두 비 COUNT의 열을 추가하십시오 :

    그룹이에 다른 두 비 COUNT의 열을 추가하십시오 :

    select CURRENT_DATE-1 AS day, 
    model.name, 
    attempt.type, 
    CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END, 
    count(*) 
    from attempt attempt, prod_hw_id prod_hw_id, model model
    where time >= '2013-11-06 00:00:00'  
    AND time < '2013-11-07 00:00:00'
    AND attempt.hard_id = prod_hw_id.hard_id
    AND prod_hw_id.model_id = model.model_id
    group by 1,2,3,4
    order by model.name, attempt.type, attempt.result;
    
  4. ==============================

    4.TSQL I의 경우 캡슐화 case 문에 같은 외부에 적용됩니다. 미래 조인 및 위치 참조에 대한 필요성을 피할 수에 두 번 기록 된 경우 문이 필요에서이 방지 나, 별칭에 의한 경우 문을 참조 할 수 있습니다.

    TSQL I의 경우 캡슐화 case 문에 같은 외부에 적용됩니다. 미래 조인 및 위치 참조에 대한 필요성을 피할 수에 두 번 기록 된 경우 문이 필요에서이 방지 나, 별칭에 의한 경우 문을 참조 할 수 있습니다.

    select oa.day, 
    model.name, 
    attempt.type, 
    oa.result
    COUNT(*) MyCount 
    FROM attempt attempt, prod_hw_id prod_hw_id, model model
    WHERE time >= '2013-11-06 00:00:00'  
    AND time < '2013-11-07 00:00:00'
    AND attempt.hard_id = prod_hw_id.hard_id
    AND prod_hw_id.model_id = model.model_id
    OUTER APPLY (
        SELECT CURRENT_DATE-1 AS day,
         CASE WHEN attempt.result = 0 THEN 0 ELSE 1 END result
        ) oa    
    group by oa.day, 
    model.name, 
    attempt.type, 
    oa.result
    order by model.name, attempt.type, oa.result;
    
  5. from https://stackoverflow.com/questions/19848930/group-by-case-statement by cc-by-sa and MIT license