0

特定の列に表示される頻度をカウントし、値を列、頻度をデータとして新しいテーブルを作成したいと思います。例:

create table users
(id number primary key, 
name varchar2(255));

insert into users  values (1, 'John');
insert into users  values (2, 'Joe');
insert into users  values (3, 'Max');

create table meals
(id number primary key,
user_id number,
food varchar2(255));

insert into meals values (1, 1, 'Apple');
insert into meals values (2, 1, 'Apple');
insert into meals values (3, 1, 'Orange');
insert into meals values (4, 1, 'Bread');
insert into meals values (5, 1, 'Apple');
insert into meals values (6, 2, 'Apple');
insert into meals values (7, 2, 'Bread');
insert into meals values (8, 2, 'Bread');
insert into meals values (9, 2, 'Apple');
insert into meals values (10, 3, 'Orange');
insert into meals values (11, 3, 'Bread');
insert into meals values (12, 3, 'Bread');

だから私はさまざまなユーザーと彼らの食事(ここではパン、アップル、オレンジ)を手に入れました。すべてのユーザーについて、彼がさまざまな食べ物をどのくらいの頻度で食べたかを知りたいと思います。次のクエリは、私が望むことを正確に実行します。

select 
(select count(id) from meals where meals.user_id = users.id and meals.food = 'Apple') as count_apple,
(select count(id) from meals where meals.user_id = users.id and meals.food = 'Orange') as count_orange,
(select count(id) from meals where meals.user_id = users.id and meals.food = 'Bread') as count_bread
from users;

問題は、これは本当に遅いことです。特に、10万人以上のユーザーと数十種類の食べ物を入手した場合はなおさらです。より高速な方法があると確信していますが、この問題を解決するのに十分なSQLの経験がありません。

4

1 に答える 1

1

11gを使用している場合は、次のpivotように演算子を使用できます。

select * from (
  select user_id, food from meals
)
pivot (count(*) as count for (food) in ('Apple', 'Orange', 'Bread'));

それ以外の場合は、手動でピボットする必要があります。

select user_id, 
       sum(case when food = 'Apple' then 1 else 0 end) count_apple, 
       sum(case when food = 'Orange' then 1 else 0 end) count_orange, 
       sum(case when food = 'Bread' then 1 else 0 end) count_bread
from   meals
group  by user_id

いずれの場合も、mealsテーブルにアクセスするのは1回だけなので、これらは元のアプローチよりも高速である必要があります。

于 2013-01-26T16:08:06.433 に答える