Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

SELECT ID FROM <SomeTable> WHERE ID IN (3, 7, 5, ...) [D7, IB6.x]


TheEd ©   (2006-02-05 05:31:00) 

Господа мастера, вопрос вроде банальный, но как заставить данный select сработать так, что бы полученный DataSet содержал записи именно в указанном порядке?

Подробности: БД - IB7.0, ID - ключевое поле, есть задача выбрать записи с ID = x1, x2, x3, ... xN в случайном порядке.

Прикол в том что иногда запрос срабатывает именно так как надо, а иногда "заботливо" сортирует записи по ID так как они в базе лежат! :(

Заранее благодарен!


evvcom   (2006-02-07 11:48:00) [1]


> Во первых: данный способ подразумевает полный скан таблицы.
>  Все предыдущие методы используют индексы, поэтому будут
> быстрее.

Не так категорично! Не всегда индексы оказываются быстрее фулскана. Если ты выбираешь более 10% записей (вроде такой порог) и не все нужные данные уже сидят в индексе, то оракловый оптимизатор никогда не выберет скан по индексу, т.к. потеря времени на физические чтения очень вероятно, окажется значительно больше потери при фулскане. Возможно, IB этого не учитывает или у него что-то построено в этом смысле не так как у оракла, но тем не менее такое категоричное заявление в этом случае, имхо, не уместно. Ну а переделав как в [18] можно и по индексу пройтись. А оракловый оптимизатор, возможно, и [16] по индексу разрулит. Надо пробовать.


sniknik   (2006-02-07 11:38:00) [2]

это можно переделать, взяв только идею
примерно на так (в принципе в FireBird должно работать, CASE там есть, мож синтаксис только поправить придется, а может и нет)
select
 case ID
   when 3 then 1
   when 7 then 2
   when 5 then 3
   ...
 end as sortorder
 ,*
from ...
where ID IN (3,7,5,...)
order by 1

но все одно, ИМХО, это не подойдет для более менее большой последовательности, хотя должно быть уже лучше чем с union (теоретически, практикой не проверено)


atruhin   (2006-02-07 11:09:00) [3]

>>evvcom ©   (07.02.06 10:50) [16]
Во первых: данный способ подразумевает полный скан таблицы. Все предыдущие методы используют индексы, поэтому будут быстрее.
Во вторых: в IB вроде нет вложенных запросов (версию 7 незнаю), так что наверное не пройдет.
Остается временная таблица, и Union all


evvcom   (2006-02-07 10:50:00) [4]

с union слишком много можем сканов таблицы получить, с помощью индексов можно снизить, но физические чтения блоков все равно могут получиться больше, чем в других вариантах реализации. Может для IB это и не так, я сужу по Ораклу.
Есть еще вариант с одним сканом и без временной таблицы (опять же оракловый), хотя в IB, думаю, case тоже должен быть:
select *
from (
 select
   *,
   case ID
     when 3 then 1
     when 7 then 2
     when 5 then 3
     ...
     else null
   end as sortorder
 from ...
)
where sortorder is not null
order by sortorder;


Polevi   (2006-02-06 15:24:00) [5]

гы, прям стих получился :-)


Polevi   (2006-02-06 15:23:00) [6]

xml универсален, кто знает тот поймет
кому нраится всюду CREATE #T втыкать - вперед, труба зовет


Виталий Панасенко   (2006-02-06 10:45:00) [7]

http://polesoft.da.ru- UDF (InitRandom/GetRandom)
select field1, field2,...,fieldN, getrandom(1000) fieldN+1 from table
order by fieldN+1


TheEd   (2006-02-05 21:42:00) [8]

определённо с временной таблицей красивее: union, если записей много будет очень тяжёл (см. sniknik ©   (05.02.06 13:05) [7] - он прав!)


TheEd   (2006-02-05 21:34:00) [9]

to sniknik
Спасибо, помогло!


atruhin   (2006-02-05 16:02:00) [10]

>>лучше уж OpenXml использовать
а при чем OpenXML и Firebird?


sniknik   (2006-02-05 15:58:00) [11]

Polevi ©   (05.02.06 15:46) [8]
нет,  Xml я не буду использовать, однозначно, он медленнее чем с таблицей. а метод с таблицей кстати вовсе не обязывает все идентификаторы за раз передавать... (зачем бездумно следовать написаному? там всего лиш примеры)

выдержка из статьи, раздел  "Фокус с Union" .... т.к. при тестировании производительности этот метод оказался значительно медленнее метода с OPENXML, который в свою очередь медленнее   метода итерацийи метода со вспомогательной таблицей.


Polevi   (2006-02-05 15:46:00) [12]

>sniknik ©   (05.02.06 13:05) [7]
ну раз тебе так хочется при 50 тыс лучше уж OpenXml использовать, по другому ты все равно столько идентификаторов не передашь за раз


sniknik   (2006-02-05 13:05:00) [13]

ну так методы решения те же самые, и проблемы втретятся похожие... вот представь, что в последовательности  "ID = x1, x2, x3, ... xN" N = к примеру 5 или хуже 50 тыс... и ??? с union не то что медленно, вообще работать не сможет (и без разници где запрос формировать, на сервере или клиенте. на клиенте даже хуже), с временной таблицей будет, и даже не особо напрягаясь.


Polevi   (2006-02-05 12:54:00) [14]

причем тут это, автор задал вопрос про сортировку


sniknik   (2006-02-05 12:41:00) [15]

Polevi ©   (05.02.06 12:08) [4]
> какая временная таблица, какой инкремент.. зачем
sniknik ©   (05.02.06 09:14) [2]
> писанины больше но работало бы быстрее на длинных последовательностях

http://www.sql.ru/articles/mssql/03060701ArraysAndListsInSQLServer.shtml#overview
Использование вспомогательной таблицыvs Фокус с использованием UNION.


Polevi   (2006-02-05 12:08:00) [16]

>sniknik ©   (05.02.06 09:14) [2]
какая временная таблица, какой инкремент.. зачем

select *, 1 as sortorder from .. where ..
union all
select *, 2 as sortorder from .. where ..
union all
select *, 3 as sortorder from .. where ..
order by sortorder


atruhin   (2006-02-05 12:07:00) [17]

Да точно. [2] sniknik ©   (05.02.06 09:14) - прав.
С union all все работает, только что проверил.


sniknik   (2006-02-05 09:14:00) [18]

union тоже будет сортировать, ему так "удобнее" выбирать дубликаты записей. попробовать union all, он не должен (не знаю как в IB)

вообще гарантию на порядок записей дает только ORDER BY, его я бы и использовал... в MSSQL (временная таблица с автоинкрементом и полем для внесения ID, порядок внесения будет последователен по автоинкременту...  после простой JOIN на нее нужной таблице и ORDER BY по автоинкременту. писанины больше но работало бы быстрее на длинных последовательностях)
а вот с IB не знаю как.


atruhin   (2006-02-05 07:13:00) [19]

Ты запрос формируешь динамически?
тогда формируй через UNION
select ... from .... where ID = 3
union
select ... from .... where ID = 7
union
select ... from .... where ID = 5


Наверх

Титульная страница Поиск, карта сайта Написать письмо