Помогите пожалуйста оптимизировать запрос использующий данные подзапросов

one_dude
Дата: 10.01.2013 11:42:02
Здравствуйте!
Поискал в гугле и по форуму, но похожего не нашёл.

Есть 2 таблицы, по данным из которой нужно производить расчёты.
Некотороые расчёты оперерируют с одними и теме же промежуточными результатами,
как можно переделать запрос, чтобы не выполнять каждый раз подзапросы,
а сохранять промежуточно данные и обращаться к ним, но, желательно в рамках одного запроса,
чтобы вычислялось всё сразу для всех контрактов.

Таблица contracts
id, abonent_info

Таблица charges
id, comment, date, summ, type

Сам запрос:
SELECT c.id, c.abonent_fio, 
SELECT (SUM(c.summ) WHERE ch.type = 1) as charged_amm,
SELECT (SUM(c.summ) WHERE ch.type = 2) as paid,
SELECT ((SUM(c.summ) WHERE ch.type = 1) - (SUM(c.summ) WHERE ch.type = 2)) as debt
FROM 
	contracts c
LEFT JOIN 
	charges ch	ON	ch.contract_id = c.id


Запрос максимально упрощён, на самом деле он занимает строк 40 и там значительно больше параметров для фильтрации,
с различными вариациями ch.type и суммированиями между результатами подзапроса.

Было бы очень хорошо, если бы работала такая конструкция:
[src]SELECT c.id, c.abonent_fio, 
SELECT (SUM(c.summ) WHERE ch.type = 1) as charged_amm,
SELECT (SUM(c.summ) WHERE ch.type = 2) as paid,
SELECT (charged_amm - paid) as debt
FROM 
	contracts c
LEFT JOIN 
	charges ch	ON	ch.contract_id = c.id
[/SRC]

Но, к сожалению не работает.

Очень надеюсь на вашу помощь!
tanglir
Дата: 10.01.2013 11:44:17
one_dude
Запрос максимально упрощён
Упрощён до нерабочего состояния. Прелестно.
Но по сабжу - ХШ говорит, что вам хочется вот этого:
select ...
,sum(case when ch.type=1 then c.summ else 0 end)
,sum(case when ch.type=2 then c.summ else 0 end)
from ...
one_dude
Дата: 10.01.2013 12:05:06
Благодарю за ответ!
Но, к сожалению, мне ведь всё равно придётся каждый раз сравнивать ch.type и другие параметры таблицы charges
и в итоге
select ...
,sum(case when ch.type=1 then c.summ else 0 end)
,sum(case when ch.type=2 then c.summ else 0 end)
from ...

опять превращается в

select ...
,sum(case when ch.type=1 then c.summ else 0 end)
,sum(case when ch.type=2 then c.summ else 0 end)
,sum(case when ch.type=3 then c.summ else 0 end)
,(sum(case when ch.type=2 then c.summ else 0 end) + sum(case when ch.type=1 then c.summ else 0 end))
,(sum(case when ch.type=2 then c.summ else 0 end) + sum(case when ch.type=1 then c.summ else 0 end) - sum(case when ch.type=3 then c.summ else 0 end))
from ...
Добрый Э - Эх
Дата: 10.01.2013 12:26:17
а присвоить изначально вычисленным полям алиасы и дальнейшую обработку делать на следующем уровне вложенности запроса - религия не позволяет?
select f1, f2, f1 - f2 as f3
 from 
(
select ...
,sum(case when ch.type=1 then c.summ else 0 end) as f1
,sum(case when ch.type=2 then c.summ else 0 end) as f2
from ...
) v
tanglir
Дата: 10.01.2013 12:26:37
one_dude
Но, к сожалению, мне ведь всё равно придётся
Ну, если придётся, значит, придётся. А впрочем, описанное выше можно решить, например, вот так:
select ...
,a,b,c
,b+a
,b+a-c
from (
 select ...
  ,sum(case when ch.type=1 then c.summ else 0 end) a
  ,sum(case when ch.type=2 then c.summ else 0 end) b
  ,sum(case when ch.type=3 then c.summ else 0 end) c
 from ...
) t0
Впрочем, не зная, что у вас на самом деле за запрос (и не генерится ли он (полу)автоматически), точнее сказать нельзя.
qwerty112
Дата: 10.01.2013 12:32:11
one_dude
Некотороые расчёты оперерируют с одними и теме же промежуточными результатами,
как можно переделать запрос, чтобы не выполнять каждый раз подзапросы,

select ...
,sum(case when ch.type=1 then c.summ else 0 end)
,sum(case when ch.type=2 then c.summ else 0 end)
,sum(case when ch.type=3 then c.summ else 0 end)
,(sum(case when ch.type=2 then c.summ else 0 end) + sum(case when ch.type=1 then c.summ else 0 end))
,(sum(case when ch.type=2 then c.summ else 0 end) + sum(case when ch.type=1 then c.summ else 0 end) - sum(case when ch.type=3 then c.summ else 0 end))
from ...


вам, чиста, с "эстетической" стороны запрос не нравится, или в чём проблема ... ?

1
select xz1, xz2, xz3,
xz1+xz2 as xz12,
xz1+xz2-xz3 as xz123,
...

from

(select ...
,sum(case when ch.type=1 then c.summ else 0 end) as xz1
,sum(case when ch.type=2 then c.summ else 0 end) as xz2
,sum(case when ch.type=3 then c.summ else 0 end) as xz3
from ...) a


2
select ...
,sum(case when ch.type=1 then c.summ else 0 end)
,sum(case when ch.type=2 then c.summ else 0 end)
,sum(case when ch.type=3 then c.summ else 0 end)
,sum(case when ch.type in (1,2) then 1 end * c.summ)
,sum(case when ch.type=2 then 1 when ch.type in (1,3) then -1 end * c.summ) 
from ...
tanglir
Дата: 10.01.2013 12:37:16
one_dude
чтобы не выполнять каждый раз подзапросы,
И, кстати, это не "подзапросы", и уменьшения производительности (заметного) в вашем варианте не будет.
one_dude
Дата: 10.01.2013 15:01:02
Большое Спасибо всем!
Буду пробовать предложенные варианты.
javajdbc
Дата: 10.01.2013 17:31:16
one_dude
Здравствуйте!
Поискал в гугле и по форуму, но похожего не нашёл.

Есть 2 таблицы, по данным из которой нужно производить расчёты.
Некотороые расчёты оперерируют с одними и теме же промежуточными результатами,
как можно переделать запрос, чтобы не выполнять каждый раз подзапросы,
а сохранять промежуточно данные и обращаться к ним, но, желательно в рамках одного запроса,
чтобы вычислялось всё сразу для всех контрактов.

Таблица contracts
id, abonent_info

Таблица charges
id, comment, date, summ, type

Сам запрос:
SELECT c.id, c.abonent_fio, 
SELECT (SUM(c.summ) WHERE ch.type = 1) as charged_amm,
SELECT (SUM(c.summ) WHERE ch.type = 2) as paid,
SELECT ((SUM(c.summ) WHERE ch.type = 1) - (SUM(c.summ) WHERE ch.type = 2)) as debt
FROM 
	contracts c
LEFT JOIN 
	charges ch	ON	ch.contract_id = c.id


Запрос максимально упрощён, на самом деле он занимает строк 40 и там значительно больше параметров для фильтрации,
с различными вариациями ch.type и суммированиями между результатами подзапроса.

Было бы очень хорошо, если бы работала такая конструкция:
[src]SELECT c.id, c.abonent_fio, 
SELECT (SUM(c.summ) WHERE ch.type = 1) as charged_amm,
SELECT (SUM(c.summ) WHERE ch.type = 2) as paid,
SELECT (charged_amm - paid) as debt
FROM 
	contracts c
LEFT JOIN 
	charges ch	ON	ch.contract_id = c.id
[/SRC]

Но, к сожалению не работает.

Очень надеюсь на вашу помощь!


>> Было бы очень хорошо, если бы работала такая конструкция:

если очень хочется, то можно!

select 
   @a:= sum(abc) trali_vally,
   @b:= sum(def) galli_bally,
   @a + @b gali_vally
from 
   atable,
(select @a:=0.0, @b:=0.0) zz
group by hhh
javajdbc
Дата: 10.01.2013 17:33:46
не, так наверно не катит, скорее:
select 
   @a:= (select sum(abc) from zzz) trali_vally,
   @b:=  (select sum(def) from zzz) galli_bally,
   @a + @b gali_vally
from 
   atable,
(select @a:=0.0, @b:=0.0) zz