2014-10-01 2 views
3

Я использую Oracle SQL, и мне нужна помощь с жестким запросом.Жесткий запрос с агрегацией

У меня есть две таблицы (table_A):

GroupID (int) 
ClientID (int) 
Age (int) 

(table_B):

GroupID (int) 
Budget (int) 

Мой запрос должен сделать для каждой группы клиентов:

  • Вычислить среднее возрастов группы
  • Рассчитать средний бюджет каждого клиента с возрастом, как средний возраст (возраст может быть больше или меньше в 1). Например: Average_Age - 1 < < Average_Age Average_Age +-
  • Output value: (бюджет)/(средний бюджет)

Например: table_A:

GroupID | ClientID | Age 
    A | 11  | 26 
    A | 22  | 27 
    A | 33  | 21 
    B | 44  | 22 
    B | 55  | 29 
    B | 66  | 25 
    C | 77  | 23 
    C | 88  | 22 
    C | 99  | 20 
    D | 111  | 24 
    D | 222  | 26 
    D | 333  | 25 

table_B:

GroupID | Budget 
    A | 100 
    B | 200 
    C | 300 
    D | 400 

Ни одно из значений в таблицах не является исправлено. Пример расчета выходного значения Группа A:

  • Средний возраст в группе А: (27 + 27 + 21)/3 = 24.6
  • В ClientIDs с возрасте от 23-25 ​​являются: 66, 77, 111, 333. Их средний бюджет: (200 + 300 + 400 * 2)/4 = 325
  • выходное значение должно быть: 100/325 = 0,307

в таблице вывод должен быть

GroupID | Output Value 
    A  |  0.307 
    B  |  .... 
    C  |  .... 
    D  |  .... 

Любые рекомендации, как это сделать? Я пробовал так много способов. Я чувствую себя потерянным.

+0

'Ни одно из значений в таблицах не фиксированы ». Итак, все ли фиксированные значения? (Для ясности) – Siyual

+0

Извините. Все они не фиксированы (я изменил его выше). – Omri

ответ

1

Подготовьте тестовые данные (фиксированный опечатка в имени и типа):

drop table table_a; 

create table table_a(
GroupID varchar2(10), 
ClientID int, 
Age  int 
); 

drop table table_b; 

create table table_b(
GroupID varchar2(10), 
Budget int 
); 


insert into table_a values('A', 11 , 26); 
insert into table_a values('A', 22 , 27); 
insert into table_a values('A', 33 , 21); 
insert into table_a values('B', 44 , 22); 
insert into table_a values('B', 55 , 29); 
insert into table_a values('B', 66 , 25); 
insert into table_a values('C', 77 , 23); 
insert into table_a values('C', 88 , 22); 
insert into table_a values('C', 99 , 20); 
insert into table_a values('D', 111 , 24); 
insert into table_a values('D', 222 , 26); 
insert into table_a values('D', 333 , 25); 

insert into table_b values('A', 100); 
insert into table_b values('B', 200); 
insert into table_b values('C', 300); 
insert into table_b values('D', 400); 

commit; 

сам запрос:

select a1.GroupId, a2.groupid, a2.clientid, b1.budget/avg(b2.budget) over(partition by a1.groupid) as avg_budget 
from (select GroupId, trunc(avg(age)) as avg_age 
     from table_a 
     group by GroupId 
    ) a1 
inner join table_a a2 
    on a2.age between a1.avg_age - 1 and a1.avg_age + 1 
inner join table_b b1 
    on b1.groupid = a1.groupid  
inner join table_b b2 
    on b2.groupid = a2.groupid  
order by a1.GroupId, a2.clientid 
;    

Результат:

GROUPID GROUPID_1 CLIENTID AVG_BUDGET 
A B 66 0.307692307692308 
A C 77 0.307692307692308 
A D 111 0.307692307692308 
A D 333 0.307692307692308 
B A 11 0.666666666666667 
B B 66 0.666666666666667 
B D 111 0.666666666666667 
B D 222 0.666666666666667 
B D 333 0.666666666666667 
C A 33 1.33333333333333 
C B 44 1.33333333333333 
C C 88 1.33333333333333 
C C 99 1.33333333333333 
D A 11 1.33333333333333 
D B 66 1.33333333333333 
D D 111 1.33333333333333 
D D 222 1.33333333333333 
D D 333 1.33333333333333 
+0

WOW. Большое спасибо. Это вовсе не тривиальный запрос.Я не уверен, что полностью понял запрос. У меня есть несколько вопросов: 1. Почему вы использовали функцию trunc()? 2. Почему вы дважды использовали таблицу «table_b» во внутреннем соединении? 3. Мне нужно продлить запрос еще двумя столбцами в итоговой таблице: в дополнение к «Средний возраст в группе А» на первом этапе мне нужно «Максимальный возраст в группе А» и «Минимальный возраст в группе А». Все, что мне нужно, это добавить два новых столбца во внутренний выбор с помощью «trunc (max (age)» и «trunc (min (age))» и еще два во внешнем? – Omri

+0

К сожалению, я не могу использовать ваш запрос. Это слишком много времени. Каждая из таблиц содержит около 20 000 записей. Последнее предложение - запустить этот запрос на гораздо больших таблицах (в 10 раз больше). Есть ли способ ускорить выполнение запроса? – Omri

+0

1. Вы сказали: Average_Age - 1 24. 2. Чтобы получить то, что вам нужно. Пожалуйста, внимательно изучите запрос - он имеет разный уровень группировки, поэтому он требует, чтобы я присоединился /, я думаю, вы можете заменить его аналитической функцией, если хотите. Это тебе решать. 3. Это уже вы знаете, что вам нужно. Я дал вам базовую идею, которую вы можете применить к реальной задаче. – Rusty

0
select Q1.GroupID, Q2.Budget/Q1.Budget_avg as Output_value from 
(
select GroupID,ClientID,avg(budget) as Budget_avg from table_A A,table_B B 
where A.GroupID =B.GroupID 
group by GroupID,ClientID 
) Q1,(select GroupID,Budget from table_B) Q2 
where Q1.GroupID = Q2.GroupID 

Вы можете попробовать это и сообщить мне, если это сработает для вас?

+0

Я только что попробовал. Это не работает ... – Omri

Смежные вопросы