Главная Новые темы Список тем Задать вопрос Поиск  

Форум "DataBase и SQL"


Язык запросов баз даных


 #0 Deep © 11.05.06 11:03:35 - 11.05.06 17:40:44

IB/FireBird - несколько полей в подзапросе



Нужен вот такой запрос:

SELECT
       LO.ID,
       LO.CONTRACTOR_ID,
       LO.RECIPIENT_ID,
       LO.ORD_NUM,
       LO.ORD_DATE,
       LO.ORD_DATE_COMPLETE,
       LO.ORD_DEADLINE,
       LO.DOC_STATUS,      
      
       DC1.NAME AS CONTRACTOR_NAME,
       DC2.NAME AS RECIPIENT_NAME,
       (
                SELECT COUNT(*), SUM(VOD.WEIGHT_TOTAL)
                FROM V_ORDER_DETAIL_CALC VOD
                WHERE VOD.ORDER_ID = LO.ID
       )      
      
FROM L_ORDER LO
     LEFT JOIN D_CONTRACTOR DC1 ON (DC1.ID = LO.CONTRACTOR_ID)
     LEFT JOIN D_CONTRACTOR DC2 ON (DC2.ID = LO.RECIPIENT_ID)  

но дудки, такое не проходит. Ругается на наличие двух полей в позапросе.

                SELECT COUNT(*), SUM(VOD.WEIGHT_TOTAL)
                FROM V_ORDER_DETAIL_CALC VOD
                WHERE VOD.ORDER_ID = LO.ID


Неужто нужно разбивать на два подзапроса? Даже не думал, что он такого не умеет.... Цитата

 #1 VictorT © 11.05.06 11:42:25

что-то я вообще не очень понял этот запрос. Как должны использоваться результаты подзапроса?
 #2 clickmaker © 11.05.06 11:57:25

> Неужто нужно разбивать на два подзапроса?

скорей всего нужно. По логике, поле в подзапросе должен соответствовать псевдоним в основном. А если там несколько полей, то как?
 #3 Andrey © 11.05.06 13:36:18

>#2  clickmaker © 11.05.06 13:57:25
Именно так.

А еще могу добавить, что если в перечне полей предложения select встречаются () "скобки", компилятор считает что эти скобки содержат expression, которое должно вернуть одно значение. Ведь функции всегда возвращают одно (пусть и сложное, аля массив, но одно) значение. (Возврат через var-параметры не учитываю ибо чит и изврат, хотя сам иногда юзаю ))

Если так уж не хочется писать 2 подзапроса, дописывай таблицу подзапроса в join, агрегаты из нее в select, и делай group by по всем полям LO, DC1 и DC2.
 #4 Deep © 11.05.06 13:50:46

> дописывай таблицу подзапроса в join, агрегаты из нее в select,
> и делай group by по всем полям LO, DC1 и DC2.
думал, может можно "упростить"...      


> #2   clickmaker ©
ага, получется из-за того что нельзя "стандартным" способром прописать алиасы.... Могли бы что-то "расширенное" придумать, а то или производительсть страдает или читабельность запроса...    
 #5 Andrey © 11.05.06 17:04:03

>
 #6 Andrey © 11.05.06 17:10:52

Такой постище написал, а оперо взяло и глюкануло (

Могли бы конечно придумать, но это довольно редкий случай (когда нужно возвращать более одного поля), а чтобы такое реализовать нужно отступить от стандарта, а это чревато.

И кстати, еще мысля пришла: а ты возвращай эти 2 поля как одно ) ну тобишь приведи их оба к строке и через... ну незнаю, через разделитель какой-то. А на клиенте анализируй. Так будет быстрее работать )
 #7 clickmaker © 11.05.06 17:14:32

> Так будет быстрее работать

не факт.  Накладные расходы на склейку/парсинг, строка опять же вместо чисел.
Лучше left outer join V_ORDER_DETAIL_CALC VOD в основном запросе
 #8 Andrey © 11.05.06 17:40:44

>#7 clickmaker
>> Так будет быстрее работать
>не факт.
Не факт, что не факт )
Если для вычисления group by компилятор сторит индекс (а так он делает часто), склейка/парсинг полей будут на порядок быстрее чем left join.

Да и по сути что такое left join... это проход по мастер-таблице, и для каждой записи проход по индексу детаил-таблици.
А что такое подзапрос... Это тот же проход по записям мастер-таблици, и для каждой записи запрос к детаил-таблице (заметте, скомпилированый запрос по индексу в которм меняется только значение ключа).

Вобщем теоретически, если планировщик не косячит, запросы должны выполятся с одиноковой скоростью если из второго варианта выкинуть group by. А за счет group by добавляется лишняя сортировка, а это тормоза.

Вот... теоретически так )


P.S. В исходниках сегодня встретил забавный коментарий:
function TbuField.Compare(ARecord: TbuRecord; AField2: TbuField; ARecord2: TbuRecord): integer;
begin
  if FDataType = AField2.DataType then
  begin
    Result := FPhisical.Compare(GetPValue(ARecord), AField2.GetPValue(ARecord2));
  end
    else
  begin
    ErrorCompare;
    Result := 0; // fuck compiler
  end;
end;




  • Написать ответ

    Имя: Регистрация HTML?
    smiles смайлики
    Потом перейти в:    
    паутина



      ©  webest.net, 2002-2007  

    top.mail.ru
    » Бесплатный счетчик посещений
    » Рейтинг сайтов