복붙노트

[SQL] SQL의 다른 컬럼의 각 값에 대해 가장 일반적인 값을 가져옵니다

SQL

SQL의 다른 컬럼의 각 값에 대해 가장 일반적인 값을 가져옵니다

나는이 같은 테이블이 있습니다 :

 Column  | Type | Modifiers 
---------+------+-----------
 country | text | 
 food_id | int  | 
 eaten   | date | 

그리고 각 국가, 내가 가장 자주 먹게되는 음식을 싶어. I는 (내가 포스트 그레스를 사용하고 있습니다) 생각할 수있는 최선 :

CREATE TEMP TABLE counts AS 
   SELECT country, food_id, count(*) as count FROM munch GROUP BY country, food_id;

CREATE TEMP TABLE max_counts AS 
   SELECT country, max(count) as max_count FROM counts GROUP BY country;

SELECT country, max(food_id) FROM counts 
   WHERE (country, count) IN (SELECT * from max_counts) GROUP BY country;

마지막 문에서 GROUP BY 및 최대 ()는 두 개의 서로 다른 음식이 동일한 수를 가지고 관계를, 휴식이 필요하다.

이것은 개념적으로 간단하게 뭔가 많은 일처럼 보인다. 그것을 할 수있는 더 정직 방법이 있나요?

해결법

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

    1.이 질문에 질문을 받았다 후 PostgreSQL은 올해 8.4에서 윈도우 함수에 대한 지원을 소개했다. 그것은 다음과 같이 오늘 해결 될 수 있음을 주목할 필요가있다 :

    이 질문에 질문을 받았다 후 PostgreSQL은 올해 8.4에서 윈도우 함수에 대한 지원을 소개했다. 그것은 다음과 같이 오늘 해결 될 수 있음을 주목할 필요가있다 :

    SELECT country, food_id
      FROM (SELECT country, food_id, ROW_NUMBER() OVER (PARTITION BY country ORDER BY freq DESC) AS rn
              FROM (  SELECT country, food_id, COUNT('x') AS freq
                        FROM country_foods
                    GROUP BY 1, 2) food_freq) ranked_food_req
     WHERE rn = 1;
    

    위는 관계를 끊어집니다. 당신이 관계를 중단하지 않으려면, 당신은 DENSE_RANK을 사용할 수 있습니다 () 대신.

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

    2.지금은 더 간단하다 : PostgreSQL의 9.4 모드 () 함수를 소개 :

    지금은 더 간단하다 : PostgreSQL의 9.4 모드 () 함수를 소개 :

    select mode() within group (order by food_id)
    from munch
    group by country
    

    (user2247323의 예와 같이) 반환 :

    country | mode
    --------------
    GB      | 3
    US      | 1
    

    여기 문서를 참조하십시오 : https://wiki.postgresql.org/wiki/Aggregate_Mode

    https://www.postgresql.org/docs/current/static/functions-aggregate.html#FUNCTIONS-ORDEREDSET-TABLE

  3. ==============================

    3.

    SELECT DISTINCT
    "F1"."food",
    "F1"."country"
    FROM "foo" "F1"
    WHERE
    "F1"."food" =
        (SELECT "food" FROM
            (
                SELECT "food", COUNT(*) AS "count"
                FROM "foo" "F2" 
                WHERE "F2"."country" = "F1"."country" 
                GROUP BY "F2"."food" 
                ORDER BY "count" DESC
            ) AS "F5"
            LIMIT 1
        )
    

    글쎄, 난 서둘러 쓴 정말 잘 확인하지 않았다. 하위 선택은 매우 느릴 수도 있지만,이 짧은 내가 생각할 수있는 것이 가장 간단한 SQL 문입니다. 내가 덜 취해있을 때 나는 아마 더 말씀 드리죠.

    추신 : 아 글쎄, "푸"내 테이블의 이름입니다, "음식"음식과 "국가"국가의 이름의 이름을 포함합니다. 샘플 출력 :

       food    |  country   
    -----------+------------
     Bratwurst | Germany
     Fisch     | Frankreich
    
  4. ==============================

    4.이 시도:

    이 시도:

    Select Country, Food_id
    From Munch T1
    Where Food_id= 
        (Select Food_id
         from Munch T2
         where T1.Country= T2.Country
         group by Food_id
         order by count(Food_id) desc
          limit 1)
    group by Country, Food_id
    
  5. ==============================

    5.이 같은 시도

    이 같은 시도

    select country, food_id, count(*) cnt 
    into #tempTbl 
    from mytable 
    group by country, food_id
    
    select country, food_id
    from  #tempTbl as x
    where cnt = 
      (select max(cnt) 
      from mytable 
      where country=x.country 
      and food_id=x.food_id)
    

    이것은 하나의 선택으로 모두를 넣을 수 있지만, 지금은 그것으로 주위를 깨끗이 할 시간이 없습니다.

    행운을 빕니다.

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

    6.여기에 모든 임시 테이블없이 그것을 할 방법은 다음과 같습니다

    여기에 모든 임시 테이블없이 그것을 할 방법은 다음과 같습니다

    편집 : 단순화

    select nf.country, nf.food_id as most_frequent_food_id
    from national_foods nf
    group by country, food_id 
    having
      (country,count(*)) in (  
                            select country, max(cnt)
                            from
                              (
                              select country, food_id, count(*) as cnt
                              from national_foods nf1
                              group by country, food_id
                              )
                            group by country
                            having country = nf.country
                            )
    
  7. ==============================

    7.

    SELECT country, MAX( food_id )
      FROM( SELECT m1.country, m1.food_id
              FROM munch m1
             INNER JOIN ( SELECT country
                               , food_id
                               , COUNT(*) as food_counts
                            FROM munch m2
                        GROUP BY country, food_id ) as m3
                     ON m1.country = m3.country
             GROUP BY m1.country, m1.food_id 
            HAVING COUNT(*) / COUNT(DISTINCT m3.food_id) = MAX(food_counts) ) AS max_foods
      GROUP BY country
    

    내가 관계를 파괴하지 않도록 MAX (.) GROUP BY 좋아한다 ... (가) 임의적으로 어떤 방법으로 가입하기에 가장 최근의 하나를 선택 먹은 날짜를 통합 할 수있는 방법이 꼭있다 ...

    난 당신이 라이브 데이터에서 실행하면이 일에 대한 쿼리 계획에 관심이 있어요!

  8. ==============================

    8.

    select country,food_id, count(*) ne  
    from   food f1  
    group by country,food_id    
    having count(*) = (select max(count(*))  
                       from   food f2  
                       where  country = f1.country  
                       group by food_id)  
    
  9. ==============================

    9.여기 당신이 원하는 무엇을 제공하고 단순하고 간결 생각 성명은 다음과 같습니다

    여기 당신이 원하는 무엇을 제공하고 단순하고 간결 생각 성명은 다음과 같습니다

    select distinct on (country) country, food_id
    from munch
    group by country, food_id
    order by country, count(*) desc
    

    나를 어떻게 생각하는지 알려 주시기 바랍니다.

    BTW, 기능에 대한 뚜렷한는 포스트 그레스에서만 사용할 수 있습니다.

    예를 들면 소스 데이터 :

    country | food_id | eaten
    US        1         2017-1-1
    US        1         2017-1-1
    US        2         2017-1-1
    US        3         2017-1-1
    GB        3         2017-1-1
    GB        3         2017-1-1
    GB        2         2017-1-1
    

    산출:

    country | food_id
    US        1
    GB        3
    
  10. from https://stackoverflow.com/questions/344665/get-most-common-value-for-each-value-of-another-column-in-sql by cc-by-sa and MIT license