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

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

Векторные запросы. Оракл и все остальные СУБД


Страницы:   1 2 3

ANB ©   (2008-02-08 12:48:00) 

В честь пятницу разомнем мозги ?
Классическая задача на векторные запросы.
Часто задают и частенько решения частные.
Имеем
Table1
(
 ID,
 F1,
 F2,
 F3,
 F4
)
и
Table2
(
 ID,
 F5,
 F6,
 F7,
 F8
)
Задача - выбрать все записи из Table1 и по одной, ей соответсвующей в Table2.
Если бы Table1 ссылалась на Table2 многие к одному - лефт джойн и полное счастье.
Однако проблема наоборот.
Добавляем в Table2 поле ID_Table1 (и соответствующий FK). Связка многие к одному.

Нужно - вытащить все записи из Table1 и все поля Table2, привязанные к таблице1, но только по одной записи (которая в группе имеет самое большое поле F5).

Кто как это делает в разных субд ?


Johnmen   (2008-02-12 17:05:00) [21]


> Тут используется функция в соединении.

М-дя...
Вообще-то соединение это чуть повыше, первое условие в where.
М.б. стОит подчитать теорию?


ANB   (2008-02-12 16:45:00) [22]


> SELECT * FROM Table1 T1, Table2 T2
> WHERE (T1.ID=T2.ID) AND
> ((SELECT MAX(MyFunc(T3.F5,T3.F6,T3.ID)) FROM Table2 T3 WHERE
> T1.ID=T3.ID) = MyFunc(T2.F5,T2.F6,T2.ID))


Тут используется функция в соединении.


> Ещё раз - где ты увидел фулскан?

Фуллскан я сам включаю по надобности хинтами.


Johnmen   (2008-02-12 16:35:00) [23]

Ещё раз - где ты увидел фулскан?
М.б. у нас разные понятия о том, что это? Тогда повторю [27].

Использование же в запросе функций однозначно отрубает возможность распараллелится,

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

а в where части - использование индекса

Да, индекс не используется. А какой у тебя индекс(ы)?
И разве использование индексов - это самоцель?

Короче, ты не теоретизируй, а смотри на практически полученные результаты на реальных данных.


ANB   (2008-02-12 16:01:00) [24]


> Где это "фулл скан" ты увидел? И что ты под этим подразумеваешь?

Если в таблице больше 10 миллионов записей, при этом из них выбирается и джойнится с другими (большими) таблицами более миллиона, то распаралеленный фулсканн по всем таблицам однозначно быстрее.

А вот какой метод применять - это уже в зависимости от задачи.
Использование же в запросе функций однозначно отрубает возможность распараллелится, а в where части - использование индекса. Можно, конечно, повесить функциональный индекс, но он не решит проблему больших объемов.


Johnmen   (2008-02-12 14:26:00) [25]


> ANB   (12.02.08 14:21) [26]
> Сдохнет такой запрос.

Ты проверил?

1) на малых объемах - не подключаться индексы

Что значит "не подключатся"? А на больших "подключатся"?

2) на больших объемах не будет распараллеливаться фулл скан.

Где это "фулл скан" ты увидел? И что ты под этим подразумеваешь?


ANB   (2008-02-12 14:21:00) [26]


> Johnmen ©   (12.02.08 13:43) [25]

Сдохнет такой запрос.
1) на малых объемах - не подключаться индексы
2) на больших объемах не будет распараллеливаться фулл скан.
Иначе было бы все ок - самое удобное решение.
Хотя, если  запросы частые, мона денормализовать Т2, т.е. триггером считать спец. поле и на это поле повесить индекс.


Johnmen   (2008-02-12 13:43:00) [27]


> ANB   (12.02.08 11:17) [21]

Тогда делаем так.
1. пишем функцию (MyFunc) преобразования полей F5, F6 и ID к строковому виду:
YYYY.MM.DD00000006660000000123, где 10 первых символов получены из F5, вторые 10 - из F6 и третьи 10 - из ID.
2. собственно сам запрос (из [4] с учетом исправления ошибки) теперь такой:
SELECT * FROM Table1 T1, Table2 T2
WHERE (T1.ID=T2.ID) AND
((SELECT MAX(MyFunc(T3.F5,T3.F6,T3.ID)) FROM Table2 T3 WHERE T1.ID=T3.ID) = MyFunc(T2.F5,T2.F6,T2.ID))


ANB   (2008-02-12 13:12:00) [28]


> т.е. наибольшему Ф6 соответствует наибльший ID

К сожалению, допускается противоречие. Юзер руками может это поле перебивать - иначе нафиг бы оно не нужно было.
Ф5 и ИД - тоже порядок может не совпадать.


ЮЮ   (2008-02-12 12:45:00) [29]

> Не прнял, откуда здесь ещё F6 всплыло

Теперь увидел [19] ANB   (12.02.08 09:55)

Но если "Ф6 - интегер нумерация внутри даты" не противоречит ID-у, т.е. наибольшему Ф6 соответствует наибльший ID, то на Ф6 можно и забить.


ЮЮ   (2008-02-12 11:44:00) [30]

Не прнял, откуда здесь ещё F6 всплыло. Но если строго по [0] - [1], т.е.

последнюю запись из Table2 c максимальным F5? то

SELECT
 Table1.*, Table2.*
FROM
 Table1
 LEFT JOIN (
   SELECT
     t2.ID_Table1, Max(t2.Id) t2.ID_Table2
   FROM
     (SELECT ID_Table1, Max(F5) MaxF5 FROM Table2 GROUP BY ID_Table1) t1Max5
     JOIN Table2 t2 ON
     -- это соединение оставит те записи, где возможно дублирование t2.ID_Table1 в парах(t2.Id, t2.ID_Table1)
       (t1Max5.ID_Table1 = t2.ID_Table1) and -- индекс по t2.ID_Table1, полагаю есть
       (t1Max5.Max5 = t2.F5) -- а вот по t2.F5 очень не помешает
   GROUP
     t2.ID_Table1
 ) t1t2 ON Table1.Id = t1t2.ID_Table1
 LEFT JOIN Table2 ON t1t2.ID_Table2 = Table2.Id


MS SQL, естественно :)


ANB   (2008-02-12 11:17:00) [31]


> Какого типа F5 и F6? Каковы диапазоны их значений в жизни?

Самое частое - Ф5 - дата, Ф6 - интегер (нумерация внутри даты). Из за особенностей генерации Ф6 оно иногда может быть неуникальным.


Johnmen   (2008-02-12 10:42:00) [32]


> ANB   (12.02.08 09:55) [19]

Какого типа F5 и F6? Каковы диапазоны их значений в жизни?


ANB   (2008-02-12 09:55:00) [33]


> Тогда тебе надо определиться с
>
> но только по одной записи (которая в группе имеет самое
> большое поле F5).
>
> Если зн.полей полей одинаковы - не понятно, какую запись
> ты предпочитаешь из двух одинаковых :)))

Звиняйте, не заметил.

Задача на самом деле сложнее.
1. С самой большой комбинацией F5, F6 (как в ордер бае).
2. Комбинация не уникальна, если есть совпадения, то берем любую, но только одну. Для упрощения можно считать - с самым большим ID. Т.е. ИД уникален, то комбинация Ф5, Ф6, ИД - уникальна.

Я написал через аналитику - но громоздко и неудобно. Плюс по таблицам приходится 2 раза лазить.

Код в Кщд   (11.02.08 06:41) [11] очень даже рабочий, сами часто так пишем. Но если полей много - то тоже громоздко и неудобно.

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


Petr V. Abramov   (2008-02-12 01:14:00) [34]


> ANB   (11.02.08 15:48) [12]

ты на [9] ответишь четко?


ANB   (2008-02-11 17:39:00) [35]


> 1. Жестко попадаем, что сортировка тока по одному полю

Жестко попадаем, что сортировка в Т2 больше чем по одному полю, т.к. оператора макс(список полей) нету. А по отдельности приедет ерунда.


Stas   (2008-02-11 17:28:00) [36]

сортировать можно по любому

order by 1,2,3


ANB   (2008-02-11 17:24:00) [37]


> Ну еще так можно.

На максах :
1. Жестко попадаем, что сортировка тока по одному полю
2. Если это поле неуникально, то записи в запросе подублятся


Stas   (2008-02-11 16:50:00) [38]

ANB   (08.02.08 17:46) [7] Это почему не скомпилится?
Ну еще так можно.
select table2.F5, MAX(F1),MAX(F2)...  from
(select id_tabl1 as IDT,max(F5) mf5 from table2 GROUP BY id_tabl1) as t inner join table2 on table2.id_table1=t.idt and table2.f5=t.mf5
GROUP BY table2.F5


ANB   (2008-02-11 16:06:00) [39]

select /*+ ordered index(LH AD_CRLIM)*/
L.*, LH.*, C.*
 from (select L.CONTNUM, max(L.Btrv_Address) keep(dense_rank last order by L.DATEOPER, L.OPERNUM) id
         from CredCont C, CrLim L
        where C.Contnum in ('1', '2', '3')
          and L.Contnum(+) = C.Contnum
          and L.ACC(+) = 1
        group by L.CONTNUM) L,
      CredCont C,
      CrLim LH
where C.CONTNUM = L.Contnum
  and LH.BTRV_ADDRESS(+) = L.id

Вот такой запрос (Т1 - CredCont, T2 - CrLim) примерно похож на то, что надо. К сожалению, на всех записях он дохнет. А на ограниченной выборке, как в примере - работает шустро.


ANB   (2008-02-11 15:48:00) [40]


> Кщд   (11.02.08 06:41) [11]

А тормозить сильно будет ?


Страницы:   1 2 3

Наверх

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