как сделать так?

Андрюшка
Дата: 29.01.2001 17:42:37
Такая вот задачка имеется. Есть несколько таблиц, а имно КЛИЕНТЫ, СЧЕТА, ОПЛАТЫ. Соответственно 40 000, ~500 000, ~500 000 записей, причем последние две имеют свойство расти очень таки быстро. А надо вот чего. Выбираем из КЛИЕНТОВ кого надо и высчитываем их текущий балланс, что то вроде SUM(Payment) - SUM(InvAmount). С вложенным приложением ето дело работает долго, поскольку выбираются все, нужные и нет. А при попытке соединить JOIN'ом три таблицы, дабы выбирать из ОПЛАТ и СЧЕТОВ только те записи, которые соответствуют КЛИЕНТАМ получается какая то петрушка, суммы увеличиваются в несколько раз.

SELECT a.saskID, SUM(m.sumoketa) AS TotalPayed
FROM abonentai a INNER JOIN
mokejimai_geri m ON a.saskID = m.saskID
WHERE (a.gatve = 1)
GROUP BY a.saskID

Тут все работает. Дальше делаем так:

SELECT a.saskID, SUM(m.sumoketa) AS TotalPayed, SUM(s.moketi)
AS TotalToPay
FROM abonentai a INNER JOIN
mokejimai_geri m ON a.saskID = m.saskID INNER JOIN
saskaitos s ON a.saskID = s.saskID
WHERE (a.gatve = 1)
GROUP BY a.saskID

И все... Хана... Значения увеоичиваются в несколько раз... Такая вот хреновина... Помогите, а?
Dmitry
Дата: 29.01.2001 18:47:58
Что значит 'С вложенным приложением'?
Почему не сделать два запроса, аналогичных первому приведенному? Работать они будут быстро. А в один запрос, наверное, все запихнуть не получится. Не работае потому, что для каждой строки таблицы счетов данного клиента добавляются ВСЕ строки таблицы оплат. Таким образом, если у тебя для данного клиента M строк в таблице счетов и N строк в таблице оплат то получишь всего M*N строк, значения которых и будут просуммированы. Так что сделай два отдельных запроса и запихни их резельтаты в переменные, которые потом можно будет вычесть одну из другой. (Если нужно получить результат одновременно по нескольким клиентам, то создавать надо соответственно не 2 переменные, а 2 временных таблицы)
P.S. Интересно, из каких соображений выбирались названия таблиц и полей?
SergSuper
Дата: 30.01.2001 09:50:05
Присоединяясь к вышесказанному, хотел бы добавить что можно наверное в один запрос с помощи unit:

SELECT a.saskID, SUM(TotalPayed), SUM(TotalToPay)
from
(
SELECT a.saskID, m.sumoketa TotalPayed, $0
AS TotalToPay
FROM abonentai a , mokejimai_geri m
WHERE (a.gatve = 1) and a.saskID = m.saskID
union
SELECT a.saskID, $0, SUM(s.moketi)
FROM abonentai a, saskaitos s WHERE (a.gatve = 1)
where (a.gatve = 1) and a.saskID = s.saskID
) as a
GROUP BY a.saskID

Возможно где есть ошибки, я не проверял, но суть наверное понятна.
Если не получиться так, то одназначно можно сделать через временные таблицы.

С приветом Сергей
PS. А названия полей мне тоже понравились, надо будет у себя применить
Андрюшка
Дата: 30.01.2001 10:22:31
Привет, мудрецы.... Прежде всего спсибо за советы... Ну а теперь все по очереди. Вложенное не приложение, а представление. Из каких соображений выбирались имена полей? Из соображений понимания ентого SQL кода. Наверное все таки надо было оставить только литовский вариант...
Merlin
Дата: 30.01.2001 13:05:34
В данной постановке задачи Вам необходимо получать текущий баланс по закзачику.
Проблемы такого рода мы часто решали следующим образом:

В базу добавляется новая таблица - activity
Ключ SascID и поля накопители по каждому виду операций (счета и оплаты и т.д.
При формировании документа необходимо добавлять (отнимать) сумму документа к(из) соответствующего поля.
В этом случае получение текущего сальдо
select abonentai.SaskID,
activity.invoice_amt - activity.payment_amt - activity.credit_memo_amount + activity.payment_return_amt ...,
...
from abonentai, activity
where abonentai.SaskID = activity.SaskID

такой подход к проблеме уменьшит загрузку серевера.
Затраты на измеении таблицы activity при появлении новой операции практически незаметны, зато заметно упрощается получение текущего баланса.