Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > SQL, базы данных
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.05.2016, 15:47   #1
Vanta11a
Lawful Evil
Участник клуба
 
Аватар для Vanta11a
 
Регистрация: 13.05.2008
Сообщений: 1,208
По умолчанию join таблиц

В БД есть две таблицы:

table1 t1
Код:
key	| field1 | field2
1	| a1	 | b1
2	| a2	 | b2
3	| a3	 | b3
table2 t2
Код:
key	| field1 | field2
1	| a1	 | AAA
2	| a1	 | BBB
3	| a2	 | AAA
4	| a3	 | CCC
Мне нужно подцепить данные из t2 к t1 через left join, при этом убрав дублирование записей для t2.field2 = 'BBB' (для значения field1 == a1 в результат должно прицепиться t2.field2 = BBB вместо двух записей, для которых t2.field2 будут равны AAA и BBB)

Вариант навскидку псевдокодом:
Код:
with res1 as (select * from t2 where field2 = 'BBB'),
with res2 as ( select * from t2 where field2 != 'BBB' and field1 not in (select field1 from res1)),
result as ( (select * from res1)
union
(select * from res2) ),
select * from table1 t1
left join result r on t1.field1 = r.field1
Но мне он не нравится. Можно ли сделать изящнее?
Алгоритм - бесплатен. Поиск багов - бесплатен. Реализация алгоритма - за отдельную плату.
На форуме помогают советами и объясняют, а не пишут на халяву программы, лабы, курсачи и т.д. (c)
Vanta11a вне форума Ответить с цитированием
Старый 24.05.2016, 16:30   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Так можно
Код:
SELECT t1.*,
    CASE WHEN t21.[Key] IS NULL THEN t22.[Key] ELSE t21.[Key] END AS KeyFrom2,
    CASE WHEN t21.[Key] IS NULL THEN t22.Field2 ELSE t21.Field2 END AS Field2From2
  FROM table1 t1
    LEFT JOIN table2 t21 ON t21.field1=t1.field1 AND t21.field2='BBB'
    LEFT JOIN table2 t22 ON t22.field1=t1.field1 AND t22.field2<>'BBB'
В table2 естесно не более двух дочерних, если две, то одна из них обязательно с field2='BBB'
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 24.05.2016 в 16:33.
Аватар вне форума Ответить с цитированием
Старый 24.05.2016, 17:31   #3
Vanta11a
Lawful Evil
Участник клуба
 
Аватар для Vanta11a
 
Регистрация: 13.05.2008
Сообщений: 1,208
По умолчанию

Спасибо
Алгоритм - бесплатен. Поиск багов - бесплатен. Реализация алгоритма - за отдельную плату.
На форуме помогают советами и объясняют, а не пишут на халяву программы, лабы, курсачи и т.д. (c)
Vanta11a вне форума Ответить с цитированием
Старый 01.06.2016, 08:13   #4
Vanta11a
Lawful Evil
Участник клуба
 
Аватар для Vanta11a
 
Регистрация: 13.05.2008
Сообщений: 1,208
По умолчанию

Подниму свою тему с новым вопросом.

Есть таблица. В ней есть столбец (field1), в котором могут быть значения "ААА", "BBB", "ССС" и т.д. в любом количестве и порядке. Также есть столбец (field2), в котором указан приоритет.
Код:
field0	| field1 | field2
1	| ААА	 | 1
1	| BBB	 | 5
2	| AAA	 | 2
1	| BBB	 | 3
1	| ААА	 | 10
2	| ССС	 | 3
2	| AAA	 | 4
Таблица left join`ится по field0, причем нужно выбрать только одну строку для каждого значения в field0

Правило для выбора строки: если в field1 есть значения "ВВВ", то возвращается строка, содержащая в field1 значение "BBB" и обладающая максимальным приоритетом (field2). Если же значения "ВВВ" нет, то вернуть значения для строки, обладающей максимальным приоритетом.

Т.е. в итоге мне нужно получить в качестве присоединяемой таблицу:
Код:
field0	| field1 | field2
1	| BBB	 | 5
2	| AAA	 | 4
Не могу сообразить, какой инструмент тут можно применить. Подскажите, пожалуйста, может я вообще не в ту сторону копаю?
Алгоритм - бесплатен. Поиск багов - бесплатен. Реализация алгоритма - за отдельную плату.
На форуме помогают советами и объясняют, а не пишут на халяву программы, лабы, курсачи и т.д. (c)
Vanta11a вне форума Ответить с цитированием
Старый 01.06.2016, 09:38   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

А в какую не ту? Не вижу. Для сиквела можно было бы примерно так. Естесно не проверял, без гарантий
Код:
SELECT U.field0,
    ISNULL(U.MaxField1ForBBB,U.MaxField1) AS field1,
    CASE WHEN U.MaxField1ForBBB IS NULL
      THEN (SELECT TOP 1 T.Field2 FROM table1 T WHERE T.field0=U.field0 AND T.field1=U.MaxField1)
      ELSE 'BBB' END AS field2
  FROM (
    SELECT field0,
        MAX(CASE WHEN field2='BBB' THEN field1 ELSE NULL END) AS MaxField1ForBBB
        MAX(field1) AS MaxField1
      FROM table1
      GROUP BY field0) AS U
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 01.06.2016, 10:05   #6
Vanta11a
Lawful Evil
Участник клуба
 
Аватар для Vanta11a
 
Регистрация: 13.05.2008
Сообщений: 1,208
По умолчанию

Пытался прикрутить join внутри case - не получилось.
Пытался прикрутить его же в if - не получилось.
Пытался как-то фильтровать результаты через case - не получилось.
Пытался пробовать distinct`ы, group by и прочее - не получилось.

Т.е. понять, есть значение "BBB" в field1 или нет я смог, а вот применить это знание для фильтрации уже нет.

Если я правильно понял логику, то в примере (с учетом опечаток) происходит так:
1. Выбираются максимальные значения поля field2 для field1 = "BBB" и вообще максимальное.
2. В результирующей таблице проверяется наличие записи с "ВВВ", если она есть - возвращается соответствующее значение, если нет - то возвращается значение для максимального field2
3. Также возвращаются field0 и максимальный field2

Интересный алгоритм, еще раз спасибо. Попробую применить.
Алгоритм - бесплатен. Поиск багов - бесплатен. Реализация алгоритма - за отдельную плату.
На форуме помогают советами и объясняют, а не пишут на халяву программы, лабы, курсачи и т.д. (c)
Vanta11a вне форума Ответить с цитированием
Старый 05.06.2016, 18:17   #7
varich
Пользователь
 
Регистрация: 01.03.2013
Сообщений: 22
По умолчанию

1.а обязательно заталкивать всю логику в один селект?
2.ваш пример не соответствует описанной логике.

Последний раз редактировалось varich; 05.06.2016 в 18:40.
varich вне форума Ответить с цитированием
Старый 08.06.2016, 15:15   #8
Vanta11a
Lawful Evil
Участник клуба
 
Аватар для Vanta11a
 
Регистрация: 13.05.2008
Сообщений: 1,208
По умолчанию

Было крайне желательно, чтобы вся эта радость выполнялось одним запросом, т.к. результат этого SELECT`a джойнился еще к куче таблиц.
Она и выполнилась, спасибо Аватар`у с его алгоритмом выборки.

А несоответствие примера - можете сказать, в чем конкретно?
Алгоритм - бесплатен. Поиск багов - бесплатен. Реализация алгоритма - за отдельную плату.
На форуме помогают советами и объясняют, а не пишут на халяву программы, лабы, курсачи и т.д. (c)
Vanta11a вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Соединение 3-х таблиц оператором Join Lokos БД в Delphi 2 08.04.2013 09:58
inner join/full join SashkaSonin БД в Delphi 6 23.03.2012 17:13
Join(запрос) clbman SQL, базы данных 8 14.06.2010 15:52
UNION JOIN tools SQL, базы данных 0 05.06.2010 18:20
join wall66 SQL, базы данных 2 10.11.2008 16:44