Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / [ANSI SQL] : как сделать такую штукенцию ? / 25 сообщений из 34, страница 1 из 2
01.11.2007, 12:00
    #34909775
EugeneUragan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
Братья по разуму!
Задача элементарная, вытекает из темы "GROUP BY clause"
Сформулировать ее можно так: используя к-либо агрегатную функцию и группировку, как
простейшим способом извлечь некоторые поля найденной строки, не входящие
в столбцы, по которым осуществляется группировка.

table_1
id (primary key) group_id id21 31 82 33 83 32 84 41 95 40 9....
table_2
id_group (PK) description31 "stroka 31"32 "другкая stroka 32"33 "stroka 33"41 "stroka 41"....
Цель - извлечь строку (3, 32, 8) из таблицы table_1. В принципе надо связать по ключу с таблицей 2 (group_id -> id_group), но зная table_1.group_id это несложно.
ВОПРОС СОСТОИТ В ТОМ, КАК СОБСТВЕННО ПОЛУЧИТЬ group_id ??

Строже говоря, нам даётся id2 (вообще будем группировать, в нижеследующем запросе условие where использовано просто с целью уяснить задачу на примере исходных данных). Дали нам id2. В первой таблице находим строку с максимальным id (PK). Это ПОСЛЕДНЯЯ ВСТАВЛЕННАЯ СТРОКА (автоинкрементный ключ), ее - строку мы и ищем по условию задачи.

select t1.id2, max(t1.id) from table_1 t1 where t1.id2 = 8

получаем: 8 | 3

Вопрос:
как извлечь все оставшиеся поля из таблицы, в данном случае group_id ?

Главный вопрос:
можно ли это сделать без подзапросов?
...
Рейтинг: 0 / 0
01.11.2007, 12:21
    #34909879
ModelR
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
Дедовский способ.
Код: plaintext
select t1.id2, max(t1.id* 1000 +t1.group_id)-max(t1.id* 1000 ) group_id_of_max_id from table_1 t1 where t1.id2 =  8 
может потребоваться чуть усложнить, но идея такая.
...
Рейтинг: 0 / 0
01.11.2007, 13:27
    #34910163
EugeneUragan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
Решение интересное!
Но если свяжем, то работаем уже со строками, уже другая ситуация. В том понимании, что их не сложить, не вычесть.
Т.е. результирующий запрос должен вернуть всё же строку из связанной таблицы, а не внешний ключ.

Новая версия со строками будет выглядеть так
Код: plaintext
1.
2.
3.
4.
select t1.id2, max(t1.id) /* что тут написать чтобы получить желанную строку из t2 ? нужно поле t2.description */
 from table_1 t1 join table_2 t2 on t1.group_id = t2.id_group
--where t1.id2 = 8 /* можно с этим или без этого */
 group by t1.id2
ps В прошлой версии запроса потеряна группировка последней строчкой.
...
Рейтинг: 0 / 0
01.11.2007, 19:56
    #34911507
Bely
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
EugeneUraganГлавный вопрос:
можно ли это сделать без подзапросов? А почему такое требование?
На ANSI SQL это делается именно с подзапросами

PS: есть вариант с
WHERE group_id in (SELECT max(group_id) .... )

но тогда нельзя будет использовать суммирования по полям.
...
Рейтинг: 0 / 0
02.11.2007, 11:17
    #34912409
EugeneUragan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
select t1.id2, t2.description /* , еще разные поля */
from table_1 t1 join table_2 t2 on t1.group_id = t2.id_group
where t1.group_id = ( select max(t11.group_id) from table_1 t11 where t11.id2 = t1.id2 );

работает ооооочень долго.
Еще добавлю: таблицы содержат больше полей, в Where есть дополнительные условия, которые должны при таком способе прописываться дважды: в основном и в подзапросе.
Постановка "без подзапросов" была такой, т.к. вроде бы этот подзапрос и есть та вещь, из-за которой суммарное время выполнения очень большое.

Какие пути оптимизации (именно текста запроса)?
...
Рейтинг: 0 / 0
02.11.2007, 12:15
    #34912685
Bely
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
EugeneUraganКакие пути оптимизации (именно текста запроса)?Какой сервер БД?
...
Рейтинг: 0 / 0
02.11.2007, 12:37
    #34912798
EugeneUragan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
Сервер firebird 1.5. Отличная вещь.
...
Рейтинг: 0 / 0
02.11.2007, 13:37
    #34913061
ЮВ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
EugeneUraganselect t1.id2, t2.description /* , еще разные поля */
from table_1 t1 join table_2 t2 on t1.group_id = t2.id_group
where t1.group_id = ( select max(t11.group_id) from table_1 t11 where t11.id2 = t1.id2 );

...работает ооооочень долго.


В СУБД ЛИНТЕР запрос
Код: plaintext
1.
2.
3.
select t1.id, t1.group_id,t1.id2, t2.gdescr 
from t1,t2
where t1.group_id=t2.id_group and
t1.id = ( select max(t1.id) from t1 where t1.id2 =  8 );
ID GROUP_ID ID2 GDESCR
-- -------- --- ------
| 3| 32| 8|drugajz stroka32 |

отрабатываает очень быстро.
Может, я не совсем правильно понял суть запроса?
...
Рейтинг: 0 / 0
02.11.2007, 14:10
    #34913189
EugeneUragan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
Ну да, такой запрос не решает поставленную задачу. Тот что я приводил в предыдущем посте, корректен, но медленен.

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

Т.е. используется группировка по id2, просто переписанная через подзапрос. По всем записям.
...
Рейтинг: 0 / 0
02.11.2007, 14:36
    #34913301
Templar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
Посмотрите на план запроса. Тогда, возможно, станет понятно, почему работает медленно. И понятно, как оптимизировать.
...
Рейтинг: 0 / 0
02.11.2007, 14:46
    #34913343
EugeneUragan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
План иногда нельзя трогать вовсе.
Будем считать, что оптимизатор выбирает оптимальный план выполнения.

Тут вопрос в SQL.
Одну и ту же задачу можно решить разными способами.
Я нашёл один, его привёл.
Возможно, вы знаете другой.
...
Рейтинг: 0 / 0
02.11.2007, 15:24
    #34913495
Templar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
Зависит от задачи: оптимизировать запрос или попытаться решить задачу разными способами.
Не факт, что они пересекаются в вашем случае.

"План иногда нельзя трогать вовсе.
Будем считать, что оптимизатор выбирает оптимальный план выполнения"
Будем. Если вы поиграете индексами или подзапросами/временными таблицами, то оптимальным будет совсем другой план.
...
Рейтинг: 0 / 0
02.11.2007, 15:28
    #34913510
EugeneUragan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
К вопросу о плане, в данном случае ситуация такова, что нужно играть именно подзапросами.
Давайте поиграем! Ваш ход.
...
Рейтинг: 0 / 0
02.11.2007, 16:27
    #34913782
EugeneUragan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
Проводим голосование.
Вопрос: запрос

Код: plaintext
1.
2.
3.
select t1.id2, t2.description /* , еще разные поля */
from table_1 t1 join table_2 t2 on t1.group_id = t2.id_group
where t1.group_id = ( select max(t11.group_id) from table_1 t11 where t11.id2 = t1.id2 );
оптимален?

Два варианта ответа:
да
нет

Хотелось бы услышать мнение тысячи человек.
...
Рейтинг: 0 / 0
02.11.2007, 16:27
    #34913784
ЮВ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
EugeneUragan
Мы обрабатываем все строки table_1, а не только одну.


Тогда такой вариант:
Код: plaintext
1.
2.
select t1.id, t1.group_id, t1.id2, t2.gdescr
from t1,t2  where t1.group_id=t2.id_group and 
t1.id in (select  max(t1.id) from t1 group by  t1.id2);
...
Рейтинг: 0 / 0
02.11.2007, 16:46
    #34913872
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
EugeneUraganПроводим голосование.
Вопрос: запрос

Код: plaintext
1.
2.
3.
select t1.id2, t2.description /* , еще разные поля */
from table_1 t1 join table_2 t2 on t1.group_id = t2.id_group
where t1.group_id = ( select max(t11.group_id) from table_1 t11 where t11.id2 = t1.id2 );
оптимален?

Два варианта ответа:
да
нет

Хотелось бы услышать мнение тысячи человек.

Что значит - "оптимален" ? Оптимальнее его вряд ли можно написать. А вот будет ли он работать быстро - нет, не будет.
...
Рейтинг: 0 / 0
02.11.2007, 16:50
    #34913890
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
EugeneUragan, у вас видимо в мозгах что-то не то творится. Вы объясните задачу в терминах предметной области, а не в виде объяснения функционирования гипотетического выдуманного вами запроса. А то у вас вообще получается какой-то мега-супер авторекурсивный запрос, который, даже если и правильный, вообще не понятно, что и выдает. И скорее всего, у вас просто база какая-то корявая, или от SQL-я вы хотите чего-то не того, что он может и должен делать.
...
Рейтинг: 0 / 0
02.11.2007, 16:51
    #34913900
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
И чего было в MySQL кроспостить, если у вас "замечательный сервер Interbase"
...
Рейтинг: 0 / 0
02.11.2007, 16:59
    #34913949
EugeneUragan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
ЮВ - вроде бы еще один отличный вариант. Надо обмозговать.

MasterZiv что же Вы такой нетерпеливый!
Всё поясню со временем.
...
Рейтинг: 0 / 0
02.11.2007, 17:16
    #34914023
Bely
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
EugeneUraganПроводим голосование.
Вопрос: запрос

Код: plaintext
1.
2.
3.
select t1.id2, t2.description /* , еще разные поля */
from table_1 t1 join table_2 t2 on t1.group_id = t2.id_group
where t1.group_id = ( select max(t11.group_id) from table_1 t11 where t11.id2 = t1.id2 );
оптимален?

Два варианта ответа:
да
нет

Хотелось бы услышать мнение тысячи человек.Я вам не скажу за всю Одессу...
но иногда будет - Да, а иногда будет - Нет
зависит от ситуации, данных, индексов и многих других волшебных пузырьков.
...
Рейтинг: 0 / 0
02.11.2007, 17:24
    #34914067
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
ЮВ пишет:

> select t1.id, t1.group_id, t1.id2, t2.gdescr
> from t1,t2 where t1.group_id=t2.id_group and
> t1.id in (select max(t1.id) from t1 group by t1.id2);

Ну тут особенно лучше-то не стало. Все равно два полных прохода по таблице
t1, один раз, возможно, по индексу.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
02.11.2007, 17:40
    #34914133
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
EugeneUraganПроводим голосование.
Вопрос: запрос

Код: plaintext
1.
2.
3.
select t1.id2, t2.description /* , еще разные поля */
from table_1 t1 join table_2 t2 on t1.group_id = t2.id_group
where t1.group_id = ( select max(t11.group_id) from table_1 t11 where t11.id2 = t1.id2 );
оптимален?

Два варианта ответа:
да
нет

Хотелось бы услышать мнение тысячи человек.Имхо, вопрос бессмысленен без указания СУБД (иногда вплоть до точной ее версии). В некоторых СУБД этот запрос вообще невозможен.
...
Рейтинг: 0 / 0
02.11.2007, 17:43
    #34914149
EugeneUragan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
mik, такие СУБД выкинем на помойку.
...
Рейтинг: 0 / 0
02.11.2007, 17:56
    #34914207
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
EugeneUraganmik, такие СУБД выкинем на помойку.Я от такой только в мае этого года избавился. Многие не сделали этого до сих пор, насколько я в курсе.
...
Рейтинг: 0 / 0
02.11.2007, 18:55
    #34914369
WildSery
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
[ANSI SQL] : как сделать такую штукенцию ?
EugeneUragan Вопрос: запрос Во-первых, FB1.5 это не ANSI. С помощью derived tables соединение с агрегатами дело плёвое.
Во-вторых, пример ты написал не по условию задачи, там должно быть не
Код: plaintext
where t1.group_id = ( select max(t11.group_id) from table_1 t11 where t11.id2 = t1.id2 );
а
Код: plaintext
where t1.id = ( select max(t11.id) from table_1 t11 where t11.id2 = t1.id2 );
EugeneUraganХотелось бы услышать мнение тысячи человек.Охота ли тебе быть посланным столько раз?
Не парь всем моск, делай процедурой.
...
Рейтинг: 0 / 0
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / [ANSI SQL] : как сделать такую штукенцию ? / 25 сообщений из 34, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]