Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Помогите с запросом / 16 сообщений из 16, страница 1 из 1
29.07.2009, 15:46
    #36115840
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Здравствуйте всем!

DB2 8.2

Есть таблицы TAB1 и TAB2, которые связаны отношением "один TAB1-ко-многим TAB2" по полю TAB1_ID. Нужно вытащить все записи TAB1, склеенные по связи только с одной(любой) записью TAB2, и, если по связи записей TAB2 нет, то заполнить её ячейки значением null.

Заранее благодарен.
С уважением, Семен Попов
...
Рейтинг: 0 / 0
29.07.2009, 16:02
    #36115904
Yokohama
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Semen Popov,

Так это же стандартный SQL... читайте про joins.
...
Рейтинг: 0 / 0
29.07.2009, 16:12
    #36115948
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Да, я знаю. Но вот засомневался.

Код: plaintext
select * from TAB1 left join TAB2 on TAB1.TAB1_ID=TAB2.TAB1_ID
будет возвращать несколько записей из TAB1, если есть несколько связанных записей TAB2. А мне нужно одну. Можно, конечно, и distinct использовать, но как-то это мне не нравится. Есть ещё варианты?
...
Рейтинг: 0 / 0
29.07.2009, 17:02
    #36116130
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Например,

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
TAB1                                        TAB2
===============                           =======================
TAB1_ID    NAME1                           TAB2_ID   TAB1_ID  NAME2 
-----------------                          --------------------------
    1       Света                             1          1       Пётр
    2       Лена                              2          1       Иван
    3       Катя                              3          2       Денис

Нужно получить табличку:

Код: plaintext
1.
2.
3.
4.
TAB1_ID    NAME1   TAB2_ID   TAB1_ID  NAME2 
----------------------------------------------
   1     Света     1           1        Пётр
   2     Лена      3           2        Денис
   3     Катя     null       null       null

left join вернёт Свету два раза.
...
Рейтинг: 0 / 0
29.07.2009, 17:46
    #36116253
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Что-то не вразумлю. Чувствую, что решение простое есть, но не могу его найти.

Пока приходит только идея с использованием distinct:
Код: plaintext
select * from TAB1 T1 left join (select * from TAB2 where TAB1_ID in (select distinct TAB1_ID from TAB2)) T2 on T1.TAB1_ID=T2.TAB1_ID
Ужасно выглядит!
...
Рейтинг: 0 / 0
29.07.2009, 18:45
    #36116391
Yokohama
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Semen Popov,
Distinct, скорее всего не получится в именно таком запросе.

Первое, что в голову пришло - это функции или селекты в селекте использовать (синтаксис оракловый):
Например,
select
t1.*,
(select t2.TAB2_ID from TAB2 t2 where t1.TAB1_ID = t2.TAB1_ID) as TAB2_ID,
(select t2.TAB1_ID from TAB2 t2 where t1.TAB1_ID = t2.TAB1_ID) as TAB1_ID,
(select t2.NAME2 from TAB2 t2 where t1.TAB1_ID = t2.TAB1_ID) as NAME2
from TAB1 t1

может и проще можно, но уже вечер и домой охота.. :)
...
Рейтинг: 0 / 0
29.07.2009, 19:45
    #36116471
Victor Metelitsa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Yokohama
select
t1.*,
(select t2.TAB2_ID from TAB2 t2 where t1.TAB1_ID = t2.TAB1_ID) as TAB2_ID,
(select t2.TAB1_ID from TAB2 t2 where t1.TAB1_ID = t2.TAB1_ID) as TAB1_ID,
(select t2.NAME2 from TAB2 t2 where t1.TAB1_ID = t2.TAB1_ID) as NAME2
from TAB1 t1

Вообще-то оно должно сломаться на записях 1:N. К тому же, что вложенные селекты, что функции (внутри которых селекты) - это чудовищные тормоза.
...
Рейтинг: 0 / 0
29.07.2009, 20:06
    #36116501
Victor Metelitsa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Semen PopovЧто-то не вразумлю. Чувствую, что решение простое есть, но не могу его найти.

Пока приходит только идея с использованием distinct:
Код: plaintext
select * from TAB1 T1 left join (select * from TAB2 where TAB1_ID in (select distinct TAB1_ID from TAB2)) T2 on T1.TAB1_ID=T2.TAB1_ID
Ужасно выглядит!
Оно будет выглядеть менее ужасно (хотя не более правильно), если пользоваться синтаксисом с WITH. Кстати, в Oracle (с 9-й версии) оно тоже есть.

Ваша задача решалась бы левым джойном TAB1 и TAB2, если бы в TAB2 не было "лишних" записей. Обозначим такую "отжатую" таблицу как TAB2X. В ней TAB1_ID будут уникальны, а TAB2_ID "какие-то". Например, минимумы.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
WITH
  TAB1K(TAB1_ID,TAB2_ID) AS (
    SELECT TAB1_ID, MIN(TAB2_ID)
    FROM TAB2
    GROUP BY TAB1_ID
  ),
  TAB2X AS (
   SELECT TX.*
   FROM TAB2 TX JOIN TAB2K TK ON (TX.TAB1_ID,TX.TAB2_ID)=(TK.TAB1_ID,TK.TAB2_ID)
  )
SELECT * 
FROM TAB1 T1 LEFT JOIN TAB2X TX ON T1.TAB1_ID = TX.TAB1_ID

Также в таблице TAB2 можно было бы завести колонку-маркер. Например, если она была бы списком пунктов в заказе, их можно было бы нумеровать последовательно 1..N для каждого TAB1_ID (назовём колонку ROW_NUM), и тогда запрос упрощается до
Код: plaintext
1.
2.
SELECT * 
FROM TAB1 T1 LEFT JOIN TAB2X TX ON T1.TAB1_ID = TX.TAB1_ID AND TX.ROW_NUM =  1 

Основываясь на этом запросе, можно вспомнить, что у нас есть ещё и OLAP-функции, одна из которых может сыграть роль упомянутой колонки.
...
Рейтинг: 0 / 0
29.07.2009, 20:15
    #36116516
Yokohama
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Victor Metelitsa,
на счет тормозов при использовании селектов согласен.На небольших объемах данных все ровно будет нормально.

А на счет сломается .. здесь сама постановка вопроса уже имеет "колизию" на одну свету приходится и Петр и Денис. В примере указан петр, но тут нужно конкретнее - первый ли попавшийся или максимальный или минимальный... короче, нужна групповая функция в самой постановке, ИМХО.
...
Рейтинг: 0 / 0
29.07.2009, 21:47
    #36116595
Victor Metelitsa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Исправления опечаток.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
WITH
--TAB1K(TAB1_ID,TAB2_ID) AS (
  TAB2K(TAB1_ID,TAB2_ID) AS (
    SELECT TAB1_ID, MIN(TAB2_ID)
    FROM TAB2
    GROUP BY TAB1_ID
  ),
  TAB2X AS (
   SELECT TX.*
   FROM TAB2 TX JOIN TAB2K TK ON (TX.TAB1_ID,TX.TAB2_ID)=(TK.TAB1_ID,TK.TAB2_ID)
  )
SELECT * 
FROM TAB1 T1 LEFT JOIN TAB2X TX ON T1.TAB1_ID = TX.TAB1_ID


Код: plaintext
1.
2.
3.
SELECT * 
--FROM TAB1 T1 LEFT JOIN TAB2X TX ON T1.TAB1_ID = TX.TAB1_ID AND TX.ROW_NUM = 1
FROM TAB1 T1 LEFT JOIN TAB2 T2 ON T1.TAB1_ID = T2.TAB1_ID AND T2.ROW_NUM =  1 
...
Рейтинг: 0 / 0
29.07.2009, 21:50
    #36116598
Victor Metelitsa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
YokohamaVictor Metelitsa,
на счет тормозов при использовании селектов согласен.На небольших объемах данных все ровно будет нормально.

Лучше не привыкать прибегать к кривым решениям, когда можно легко обойтись без них.

А на счет сломается .. здесь сама постановка вопроса уже имеет "колизию" на одну свету приходится и Петр и Денис. В примере указан петр, но тут нужно конкретнее - первый ли попавшийся или максимальный или минимальный... короче, нужна групповая функция в самой постановке, ИМХО.
Агрегатные функции не дадут вам гарантии, что эти значения будут взяты из одной и той же строки.
...
Рейтинг: 0 / 0
29.07.2009, 23:02
    #36116662
Yokohama
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Victor Metelitsa
Агрегатные функции не дадут вам гарантии, что эти значения будут взяты из одной и той же строки.
Кто говорил, что они должны браться из какой-то конкретной строчки?
Они (функции), как минимум, как-нибудь регламентируют этот процесс :)
...
Рейтинг: 0 / 0
29.07.2009, 23:53
    #36116697
Victor Metelitsa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
YokohamaКто говорил, что они должны браться из какой-то конкретной строчки?
Semen Popovсклеенные по связи только с одной(любой) записью TAB2
...
Рейтинг: 0 / 0
30.07.2009, 08:48
    #36116882
Yokohama
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Victor Metelitsa,
Ну если "конкретная" - это "любая", то тогда, конечно же вы правы... ;))
...
Рейтинг: 0 / 0
30.07.2009, 09:21
    #36116944
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Yokohama, Victor Metelitsa спасибо за участие в обсуждении.

YokohamaVictor Metelitsa,
Ну если "конкретная" - это "любая", то тогда, конечно же вы правы... ;))"Конкретная" входит в множество "любая":-) Для моей задачи это не имеет значения. Неважно, какую "конкретную" выбрать. Я специально не стал указывать в постановке вопроса с какой записью склеивать, чтобы увидеть многие варианты, а затем выбрать самый быстрый. Хотя мог бы поставить условие - например, склеивать с той записью TAB2, у которой TAB2_ID будет наименьшим.
Ваши варианты рассмотрю, попробую. Спасибо. Ещё порылся в форуме и увидел скрипт, который делает подобное.
Код: plaintext
1.
2.
3.
4.
select * from TAB1 left join (select *
from (select rownumber() over(partition by TAB1_ID) rn_, TAB2.*
from TAB2) t
where rn_= 1 ) TX on TAB1.TAB1_ID=TX.TAB1_ID
Насколько такой скрипт будет по-лучше или по-хуже? Индекс таблицы TAB2 по полю TAB1_ID существует.
...
Рейтинг: 0 / 0
30.07.2009, 10:15
    #36117074
Victor Metelitsa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с запросом
Теоретически OLAP функция (rownumber()over() - я бы ещё order by использовал внутри) должна быть выгоднее, а про индексы бы у index advisor'а спросил.

Но, как говорил какой-то Великий Классик Марксизма-Ленинизма, практика - критерий истины.
...
Рейтинг: 0 / 0
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Помогите с запросом / 16 сообщений из 16, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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