복붙노트

[SQL] GROUP BY 절에 나타나야합니다 또는 집계 함수에 사용

SQL

GROUP BY 절에 나타나야합니다 또는 집계 함수에 사용

나는 테이블을 가지고 그이 호출자 makerar '와 같은 외모

 cname  | wmname |          avg           
--------+-------------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | luffy  | 1.00000000000000000000
 spain  | usopp  |     5.0000000000000000

그리고 각 CNAME의 최대 평균을 선택합니다.

SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname;

하지만 오류가 발생합니다,

ERROR:  column "makerar.wmname" must appear in the GROUP BY clause or be used in an   aggregate function 
LINE 1: SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname;

그래서 내가 이렇게

SELECT cname, wmname, MAX(avg)  FROM makerar GROUP BY cname, wmname;

그러나 이것은 의도 된 결과를 제공하지 않으며, 아래 잘못된 출력을 나타낸다.

 cname  | wmname |          max           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | luffy  | 1.00000000000000000000
 spain  | usopp  |     5.0000000000000000

실제 결과는해야한다

 cname  | wmname |          max           
--------+--------+------------------------
 canada | zoro   |     2.0000000000000000
 spain  | usopp  |     5.0000000000000000

이 문제를 어떻게 해결에 대한 갈 수 있나요?

참고 :이 표는 이전 작업에서 작성된 도면이다.

해결법

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

    1.예, 이것은 일반적인 집계 문제입니다. SQL3 (1999) 전에 선택한 필드 절 [*]에 의해 GROUP에 표시해야합니다.

    예, 이것은 일반적인 집계 문제입니다. SQL3 (1999) 전에 선택한 필드 절 [*]에 의해 GROUP에 표시해야합니다.

    이 문제를 해결하려면, 당신은 하위 쿼리에서 집계를 계산 한 다음 보여줄 필요하려는 추가 열을 얻을 자체로 가입해야합니다 :

    SELECT m.cname, m.wmname, t.mx
    FROM (
        SELECT cname, MAX(avg) AS mx
        FROM makerar
        GROUP BY cname
        ) t JOIN makerar m ON m.cname = t.cname AND t.mx = m.avg
    ;
    
     cname  | wmname |          mx           
    --------+--------+------------------------
     canada | zoro   |     2.0000000000000000
     spain  | usopp  |     5.0000000000000000
    

    그러나 당신은 또한 간단하게 보이는 창 기능을 사용할 수 있습니다 :

    SELECT cname, wmname, MAX(avg) OVER (PARTITION BY cname) AS mx
    FROM makerar
    ;
    

    이 방법의 유일한 점은 (윈도우 함수 그룹을하지 않는) 모든 레코드를 보여줄 것입니다. 그것은 당신까지, 그래서하지만, 각 행의 국가 MAX을 (CNAME 수준에서 즉 끝나가는) 올바른 표시됩니다 :

     cname  | wmname |          mx           
    --------+--------+------------------------
     canada | zoro   |     2.0000000000000000
     spain  | luffy  |     5.0000000000000000
     spain  | usopp  |     5.0000000000000000
    

    용액을 틀림없이 적은 우아한 유일한 (CNAME, wmname)를 보여이고, 최대 값과 일치하는 튜플 :

    SELECT DISTINCT /* distinct here matters, because maybe there are various tuples for the same max value */
        m.cname, m.wmname, t.avg AS mx
    FROM (
        SELECT cname, wmname, avg, ROW_NUMBER() OVER (PARTITION BY avg DESC) AS rn 
        FROM makerar
    ) t JOIN makerar m ON m.cname = t.cname AND m.wmname = t.wmname AND t.rn = 1
    ;
    
    
     cname  | wmname |          mx           
    --------+--------+------------------------
     canada | zoro   |     2.0000000000000000
     spain  | usopp  |     5.0000000000000000
    

    [*] : 흥미롭게의 사양 종류가 아닌 그룹화 필드를 선택할 수 있습니다에도 불구하고, 주요 엔진은 정말 좋아 보인다. 오라클과의 SQLServer는 전혀이 허용되지 않습니다. MySQL은 기본적으로 허용하는 데 사용,하지만 지금은 5.7 이후 관리자 (ONLY_FULL_GROUP_BY) 수동 기능의 서버 구성에서 지원이 옵션을 사용하도록 설정해야합니다 ...

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

    2.포스트 그레스, 당신은 또한 특별한 DISTINCT ON (표현) 구문을 사용할 수 있습니다 :

    포스트 그레스, 당신은 또한 특별한 DISTINCT ON (표현) 구문을 사용할 수 있습니다 :

    SELECT DISTINCT ON (cname) 
        cname, wmname, avg
    FROM 
        makerar 
    ORDER BY 
        cname, avg DESC ;
    
  3. ==============================

    3.선택에 의해 그룹에서 비 그룹화 및 비 집계 필드를 지정하는 문제는 그 엔진이이 경우에 반환해야하는 레코드의 필드 알 수있는 방법이 없습니다. 먼저인가? 이 마지막인가? 자연스럽게 집계 결과 (최소 및 최대입니다 예외)에 해당하는지에 대한 기록은 일반적으로 없습니다.

    선택에 의해 그룹에서 비 그룹화 및 비 집계 필드를 지정하는 문제는 그 엔진이이 경우에 반환해야하는 레코드의 필드 알 수있는 방법이 없습니다. 먼저인가? 이 마지막인가? 자연스럽게 집계 결과 (최소 및 최대입니다 예외)에 해당하는지에 대한 기록은 일반적으로 없습니다.

    그러나, 해결 방법이있다 : 골재뿐만 아니라 필수 항목을합니다. 포스트 그레스,이 작업을해야합니다 :

    SELECT cname, (array_agg(wmname ORDER BY avg DESC))[1], MAX(avg)
    FROM makerar GROUP BY cname;
    

    참고 이것은 평균에 의해 주문 된 wnames의 배열을 생성하고, (포스트 그레스의 배열이 1 기이다)의 첫 번째 요소를 반환.

  4. ==============================

    4.

    SELECT t1.cname, t1.wmname, t2.max
    FROM makerar t1 JOIN (
        SELECT cname, MAX(avg) max
        FROM makerar
        GROUP BY cname ) t2
    ON t1.cname = t2.cname AND t1.avg = t2.max;
    

    순위 () 윈도우 함수를 사용하여 :

    SELECT cname, wmname, avg
    FROM (
        SELECT cname, wmname, avg, rank() 
        OVER (PARTITION BY cname ORDER BY avg DESC)
        FROM makerar) t
    WHERE rank = 1;
    

    노트

    어느 한 그룹 당 다수의 최대 값을 유지합니다. 당신은 당신이 ypercube의 대답 @ 확인해야 최대 동일한 평균 더 이상의 레코드가있는 경우에도 그룹 당 하나의 기록을합니다.

  5. ==============================

    5.나를 위해, 그것은 그러나 다만 잘못된 SQL 쿼리에 대해,는 "일반적인 집계 문제"에 대한 없습니다. 에 대한 하나의 정답 "각 CNAME의 최대 평균을 선택은 ..."이다

    나를 위해, 그것은 그러나 다만 잘못된 SQL 쿼리에 대해,는 "일반적인 집계 문제"에 대한 없습니다. 에 대한 하나의 정답 "각 CNAME의 최대 평균을 선택은 ..."이다

    SELECT cname, MAX(avg) FROM makerar GROUP BY cname;
    

    그 결과는 다음과 같습니다

     cname  |      MAX(avg)
    --------+---------------------
     canada | 2.0000000000000000
     spain  | 5.0000000000000000
    

    일반적으로 답변에서이 결과 문제 "각 그룹에 대한 최상의 결과 무엇입니까?". 우리는 스페인의 가장 좋은 결과는 5이며, 캐나다 최선의 결과 그것은 사실이다 2.이며, 오류가없는 것을 알 수있다.  우리는 또한 wmname를 표시해야하는 경우, 우리는 질문에 답해야한다 : "세트를 결과에서 wmname를 선택할 수있는 규칙은 무엇입니까" 약간의하자의 변화 입력 데이터는 실수를 명확히 :

      cname | wmname |        avg           
    --------+--------+-----------------------
     spain  | zoro   |  1.0000000000000000
     spain  | luffy  |  5.0000000000000000
     spain  | usopp  |  5.0000000000000000
    

    결과이 쿼리를 runnig에 기대 어떤 : SELECT CNAME CNAME BY makerar 그룹, wmname, MAX (평균);? 그것은 스페인 + 루피 또는 스페인 + 우솝해야 하는가? 왜? 몇 가지가 적합한 경우 결과도 결정되지 않도록, "더 나은"wmname을 선택하는 방법 쿼리에서 결정되지 않습니다. 쿼리가 정확하지 않습니다 - SQL 반환 통역 오류가 이유입니다.

    다른 단어에서 질문에 대한 정답이 없다 "스페인 그룹의 최고?". 우솝이 같은 "점수"를 가지고 있기 때문에 루피는 더 나은 우솝 이상이다.

  6. ==============================

    6.나는 최근이 문제로 실행 할 때 케이스를 사용하여 계산하려고 때 발견 그 어떤 및 계산 문 수정 문제의 순서를 변경 :

    나는 최근이 문제로 실행 할 때 케이스를 사용하여 계산하려고 때 발견 그 어떤 및 계산 문 수정 문제의 순서를 변경 :

    SELECT date(dateday) as pick_day,
    COUNT(CASE WHEN (apples = 'TRUE' OR oranges 'TRUE') THEN fruit END)  AS fruit_counter
    
    FROM pickings
    
    GROUP BY 1
    

    후자에, 나는 사과와 오렌지가 집계 함수에 나타나도록 오류를 어디서 얻었 - 대신 사용

    CASE WHEN ((apples = 'TRUE' OR oranges 'TRUE') THEN COUNT(*) END) END AS fruit_counter
    
  7. ==============================

    7.이뿐만 아니라 작동하는 것 같다

    이뿐만 아니라 작동하는 것 같다

    SELECT *
    FROM makerar m1
    WHERE m1.avg = (SELECT MAX(avg)
                    FROM makerar m2
                    WHERE m1.cname = m2.cname
                   )
    
  8. from https://stackoverflow.com/questions/19601948/must-appear-in-the-group-by-clause-or-be-used-in-an-aggregate-function by cc-by-sa and MIT license