Форум "DataBase и SQL"
Язык запросов баз даных
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 Неужто нужно разбивать на два подзапроса? Даже не думал, что он такого не умеет....
|
|
что-то я вообще не очень понял этот запрос. Как должны использоваться результаты подзапроса? |
|
> Неужто нужно разбивать на два подзапроса? скорей всего нужно. По логике, поле в подзапросе должен соответствовать псевдоним в основном. А если там несколько полей, то как? |
|
#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. |
|
> дописывай таблицу подзапроса в 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 поля как одно ) ну тобишь приведи их оба к строке и через... ну незнаю, через разделитель какой-то. А на клиенте анализируй. Так будет быстрее работать ) |
|
> Так будет быстрее работать не факт. Накладные расходы на склейку/парсинг, строка опять же вместо чисел. Лучше 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; |
Написать ответ |
|
