31

次のようなテーブルがあります。

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

そして、国ごとに、最も頻繁に食べられる食べ物を取得したいと考えています。私が考えることができる最高のもの(私はpostgresを使用しています)は次のとおりです。

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 と max() は、2 つの異なる食品のカウントが同じである同点を解消するために必要です。

これは、概念的に単純なものの場合、多くの作業のように思えます。それを行うためのより簡単な方法はありますか?

4

9 に答える 9

19

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() を使用できます。

于 2012-09-16T17:17:31.617 に答える
8
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ステートメントです。酔っ払っていないときにもっと教えてあげるでしょう。

PS:そうですね、「foo」は私のテーブルの名前です。「food」には食べ物の名前が含まれ、「country」には国の名前が含まれています。サンプル出力:

   food    |  country   
-----------+------------
 Bratwurst | Germany
 Fisch     | Frankreich
于 2008-12-05T18:44:03.150 に答える
6

これを試して:

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
于 2008-12-06T19:36:27.787 に答える
3

このようなものを試してください

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)

これはすべてを1つの選択にまとめることができますが、今はそれをいじくり回す時間がありません。

幸運を。

于 2008-12-05T18:17:57.087 に答える
3

一時テーブルなしでこれを行う方法は次のとおりです。

編集:簡略化

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
                        )
于 2008-12-05T18:23:30.213 に答える
3
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 が関係を壊すのが好きではありません...食べた日付を何らかの方法で JOIN に組み込み、最新のものを任意に選択する方法が必要です...

ライブデータで実行する場合のクエリプランに興味があります!

于 2008-12-05T20:50:05.813 に答える
3
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)  
于 2008-12-05T21:31:29.490 に答える