Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помощь в составлении запроса  [new]
arSenya
Member

Откуда:
Сообщений: 12
Требуется произвести выборочное обьединение данных.
Пусть дано 2 таблицы: T1- таблица сотрудников, и T2 -данные сотрудников
В Т1 cотрудник мощет иметь только 1 запись, а в Т2 - несколько ( в зависимости от группы)
к примеру Т1
IDName
1Иванов
2Петров
3Сидоров

Т2
IDGroup_ID
11
10
20
22
31


Объединить надо так чтобы если в Т2 есть запись с группой 1 то в итоговый результат входит она, если нет то 0
1-1
2-0
3-1

Есть вариант чтобы использовать Union

Select T1.ID,T2.Group_ID
From T1 LEFT OUTER JOIN T2 on T1.ID=T2.ID
where Group_ID=1
Union
Select T1.ID,T2.Group_ID
From T1 LEFT OUTER JOIN T2 on T1.ID=T2.ID
where Group_ID=0
and T2.ID NOT IN (Select ID From T2 where Group_ID=1)

Какие есть другие более оптимальные варианты?
15 янв 16, 23:46    [18687124]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в составлении запроса  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31822
arSenya
Какие есть другие более оптимальные варианты?
Разве не это нужно?
Select T1.ID, ISNULL(T2.Group_ID, 0) as Group_ID
From T1 
    LEFT OUTER JOIN T2 
        on T1.ID=T2.ID
        and T2.Group_ID=1
16 янв 16, 00:34    [18687234]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в составлении запроса  [new]
arSenya
Member

Откуда:
Сообщений: 12
alexeyvg,
нет, надо если нет записи с Group_ID = 1 чтобы тогда подставлялась запись с Group_ID = 0.
16 янв 16, 00:47    [18687264]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в составлении запроса  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
arSenya
alexeyvg,
нет, надо если нет записи с Group_ID = 1 чтобы тогда подставлялась запись с Group_ID = 0.

CREATE TABLE #T1 (ID int, Name varchar(50))
CREATE TABLE #T2 (ID int, Group_ID int)
INSERT #T1 
VALUES 
	(1, 'Иванов'),
	(2, 'Петров'),
	(3, 'Сидоров')

INSERT #T2
VALUES 
	(1, 1),
	(1, 0),
	(2, 0),
	(2, 2),
	(3, 1)

-- Option 1
Select T1.ID, ISNULL(T2.Group_ID, T2_0.Group_ID) as Group_ID
From #T1 T1 
    LEFT OUTER JOIN #T2 T2 
        on T1.ID=T2.ID
        and T2.Group_ID=1
    LEFT OUTER JOIN #T2 T2_0 
        on T1.ID=T2_0.ID
        and T2_0.Group_ID=0

-- Option 2
Select T1.ID, T2.Group_ID
From #T1 T1 
LEFT JOIN
(
	SELECT *, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Group_ID DESC) RID
	FROM #T2
	WHERE Group_ID IN (0,1)
) T2 ON T2.ID = T1.ID AND T2.RID = 1

-- Option 3
Select T1.ID, MAX(T2.Group_ID) AS Group_ID
From #T1 T1 
LEFT JOIN #T2 T2 ON T2.ID = T1.ID
	AND T2.Group_ID in (0,1)
GROUP BY T1.ID
16 янв 16, 02:33    [18687484]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в составлении запроса  [new]
arSenya
Member

Откуда:
Сообщений: 12
Mind,
надо посмотреть ваши варианты), вроде так работает, подставлю под реальные таблицы.
Т2 это таблица данных, там много текстовых записей, и поэтому 3ий вариант наверно не подойдет, как впрочем и второй. Но надо проверить... . Спасибо
16 янв 16, 03:24    [18687510]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в составлении запроса  [new]
aleks2
Guest
declare @T1 TABLE (ID int primary key, Name varchar(50))
declare @T2 TABLE (ID int, Group_ID int, primary key( id, Group_ID))
INSERT @T1 
VALUES 
	(1, 'Иванов'),
	(2, 'Петров'),
	(3, 'Сидоров')

INSERT @T2
VALUES 
	(1, 1),
	(1, 0),
	(2, 0),
	(2, 2),
	(3, 1)

Select T1.ID, T2.Group_ID
From @T1 as T1 
  outer apply ( select top(1) * from @T2 where ID = T1.ID and Group_ID in (0, 1) order by Group_ID desc ) as T2
16 янв 16, 07:11    [18687552]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в составлении запроса  [new]
arSenya
Member

Откуда:
Сообщений: 12
Единственный вариант который подходит это последний, так как все предыдущие рассчитаны на то что ко второй таблице ничего не присоединяется и на нее нельзя наложить никакие фильтры.
Правда я не думаю что в данном случае apply c подзапросом по каждой строке будет быстрее чем Union.
Это моя вина, я не дал полную информацию. Более конкретно будет так:

CREATE TABLE #T1 (ID int, Name varchar(50))
CREATE TABLE #T2 (ID int, Group_ID int,Prim1 varchar(50),Prim2 varchar(50),Prim3 varchar(50),isActive varchar(1))
CREATE TABLE #T3 (Group_ID int, GroupName varchar(50))
INSERT #T1
VALUES
(1, 'Иванов'),
(2, 'Петров'),
(3, 'Сидоров')

INSERT #T2
VALUES
(1, 1,'Prim111','Prim112','Prim113','N'),
(1, 0,'Prim101','Prim102','Prim103','A'),
(1, 2,'Prim121','Prim122','Prim123','A'),
(2, 0,'Prim201','Prim202','Prim203','A'),
(2, 5,'Prim251','Prim252','Prim253','A'),
(2, 2,'Prim221','Prim222','Prim223','A'),
(3, 1,'Prim311','Prim312','Prim313','A')

INSERT #T3
VALUES
(1, 'Группа 1'),
(2, 'Группа 2'),
(3, 'Группа 3'),
(4, 'Группа 4'),
(5, 'Группа 5')

Поле isActive это фильтр активности, он влияет только на результирующий набор, т.е. если есть запись в ID=1 то должна присоединиться она но в результирующем наборе сотрудник не должен быть из-за фильтра по isActive.
16 янв 16, 12:59    [18688017]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в составлении запроса  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
arSenya,

Если у вас потом JOIN к получившейся таблице, то лучше либо UNION, либо сохранять результат джойна Т1 и Т2 во временную таблицу и потом джойнить все остальное. Иначе с очень большой вероятностью у оптимизатора крышу снесет.
18 янв 16, 20:11    [18698202]     Ответить | Цитировать Сообщить модератору
 Re: Помощь в составлении запроса  [new]
arSenya
Member

Откуда:
Сообщений: 12
Mind,
ну да, сделал как сам и предлагал)
19 янв 16, 00:46    [18699062]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить