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

Откуда:
Сообщений: 333
Здравствуйте! Подскажите, пожалуйста.

Есть 2 таблицы: FactEvents (События.Факт) и PlanEvents (События.План).
Столбцы: Address (адрес), Year (год), Month (месяц), Event (событие)

Для объяснения задачи возьмем следующие данные:
FactEvents
Address Year Month Event
Ул. Ленина 1 2015 1 Событие 1
Ул. Ленина 1 2015 7 Событие 2
...


PlanEvents
Address Year Month Event
Ул. Ленина 1 2015 3 Событие 3
Ул. Ленина 1 2015 11 Событие 4
...


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

Т.е. для примера выше должно получиться:
Result
Address Year Month Event
Ул. Ленина 1 2015 1 Событие 1
Ул. Ленина 1 2015 2 Событие 1
Ул. Ленина 1 2015 3 Событие 3
Ул. Ленина 1 2015 4 Событие 3
Ул. Ленина 1 2015 5 Событие 2
Ул. Ленина 1 2015 6 Событие 2
Ул. Ленина 1 2015 7 Событие 2
Ул. Ленина 1 2015 8 Событие 2
Ул. Ленина 1 2015 9 Событие 2
Ул. Ленина 1 2015 10 Событие 4
Ул. Ленина 1 2015 11 Событие 4
Ул. Ленина 1 2015 12 Событие 4
...
6 май 15, 09:01    [17605446]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
Glory
Member

Откуда:
Сообщений: 104751
Нужна 3я таблица - со всеми комбинациями годов и месяцев
И станет все просто
6 май 15, 09:06    [17605471]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
alexFV
Member

Откуда:
Сообщений: 333
Glory
Нужна 3я таблица - со всеми комбинациями годов и месяцев
И станет все просто

Спасибо большое. Таблицу можно ввести. Но как станет просто не очень ясно. Не могли бы Вы чуть подробнее объяснить?
6 май 15, 09:18    [17605519]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
Glory
Member

Откуда:
Сообщений: 104751
alexFV
Но как станет просто не очень ясно.

Просто будет потому, что для каждой записи календаря нужно будет просто искать одну ближайшую/равную запись из FactEvents/PlanEvents
6 май 15, 09:32    [17605588]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
LexusR
Member

Откуда: Novosibirsk
Сообщений: 1887
DECLARE @Year int = 2015 
SELECT A.Address,@Year AS [Year],M.[MONTH]
,case WHEN FE.DIFF <= PE.DIFF  THEN FE.Event
      WHEN PE.DIFF IS NOT NULL THEN PE.Event
      ELSE NULL END AS Event 
FROM
(SELECT Address FROM FactEvents UNION SELECT Address FROM PlanEvents) A
CROSS JOIN 
(SELECT 1 AS [MONTH] 
UNION SELECT 2 
UNION SELECT 3 
UNION SELECT 4
UNION SELECT 5
UNION SELECT 6
UNION SELECT 7
UNION SELECT 8
UNION SELECT 9
UNION SELECT 10
UNION SELECT 11
UNION SELECT 12
     ) M
OUTER APPLY(SELECT TOP 1 ABS(Month-M.Month) AS DIFF,[EVENT] FROM FactEvents WHERE Address = A.Address AND Year = @Year ORDER BY ABS(Month-M.Month)) FE    
OUTER APPLY(SELECT TOP 1 ABS(Month-M.Month) AS DIFF,[EVENT] FROM PlanEvents WHERE Address = A.Address AND Year = @Year ORDER BY ABS(Month-M.Month)) PE    
6 май 15, 11:20    [17606163]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
alexFV
Member

Откуда:
Сообщений: 333
Glory
Просто будет потому, что для каждой записи календаря нужно будет просто искать одну ближайшую/равную запись из FactEvents/PlanEvents

Спасибо. Но вроде не одну запись для календаря надо искать. Т.к. адресов много. Причем их кол-во может быть разное из месяца в месяц. А можно привести примерную идею запроса?
6 май 15, 11:24    [17606205]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
alexFV
Member

Откуда:
Сообщений: 333
Спасибо, LexusR.
Получается не надо вводить доп. таблицу если делаем за целый год выборку. А если надо будет не за год брать данные, а за произвольный период, то тогда такой механизм не сработает, верно? Необходимо будет все-таки вводить таблицу комбинаций годов и месяцев, правильно?
6 май 15, 11:33    [17606272]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
LexusR
Member

Откуда: Novosibirsk
Сообщений: 1887
SELECT A.Address,Y.[Year] AS [Year],M.[MONTH]
,case WHEN FE.DIFF <= PE.DIFF  THEN FE.Event
      WHEN PE.DIFF IS NOT NULL THEN PE.Event
      ELSE NULL END AS Event 
FROM
(SELECT Address FROM FactEvents UNION SELECT Address FROM PlanEvents) A
CROSS JOIN (SELECT [Year] FROM FactEvents UNION SELECT [Year] FROM PlanEvents) Y
CROSS JOIN 
(SELECT 1 AS [MONTH] 
UNION SELECT 2 
UNION SELECT 3 
UNION SELECT 4
UNION SELECT 5
UNION SELECT 6
UNION SELECT 7
UNION SELECT 8
UNION SELECT 9
UNION SELECT 10
UNION SELECT 11
UNION SELECT 12
     ) M
OUTER APPLY(SELECT TOP 1 ABS(Month-M.Month) AS DIFF,[EVENT] FROM FactEvents WHERE Address = A.Address AND Year = Y.[Year] ORDER BY ABS(Month-M.Month)) FE    
OUTER APPLY(SELECT TOP 1 ABS(Month-M.Month) AS DIFF,[EVENT] FROM PlanEvents WHERE Address = A.Address AND Year = Y.[Year] ORDER BY ABS(Month-M.Month)) PE    
ORDER BY Y.[Year],M.Month
6 май 15, 11:49    [17606360]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
alexFV
Member

Откуда:
Сообщений: 333
LexusR, спасибо! Но честно сказать сложно для меня.

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

Создал таблицу Calendar
Year Month
2015 1
2015 2
2015 3
...


И ест таблица
FactEvents
Address Year Month Event
Ул. Ленина 1 2015 1 Событие 1
Ул. Ленина 1 2015 7 Событие 2


Хочу получить объединение, с заполненным событием, если оно есть
Result
Year Month Address Event
2015 1 Ул. Ленина 1 Событие 1
2015 2 Ул. Ленина 1 NULL
2015 3 Ул. Ленина 1 NULL
2015 4 Ул. Ленина 1 NULL
2015 5 Ул. Ленина 1 NULL
2015 6 Ул. Ленина 1 NULL
2015 7 Ул. Ленина 1 Событие 2
...


Подскажите, пожалуйста, с запросом.
6 май 15, 16:05    [17608201]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
o-o
Guest
declare  @Calendar table(yy int, mm int);
insert into @Calendar values
(2015,	1),
(2015,	2),
(2015,	3),
(2015,	4),
(2015,	5),
(2015,	6),
(2015,	7);

declare @FactEvents table (Address nvarchar(100), yy int, mm int, Event nvarchar(100));
insert into @FactEvents values
(N'Ул. Ленина 1',	2015,	1,	N'Событие 1'),
(N'Ул. Ленина 1',	2015,	7,	N'Событие 2');

with all_addr as
(
select distinct Address
from @FactEvents
)

select c.yy, c.mm, a.Address, f.Event
from @Calendar c cross join all_addr a
     left join @FactEvents f on c.yy = f.yy and c.mm = f.mm and a.Address = f.Address;
6 май 15, 16:25    [17608365]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4974
alexFV,

Какой-то из таких вариантов вам наверное нужен

(Календарь CROSS JOIN СписокАдресов) LEFT JOIN Событие 

(Календарь CROSS JOIN СписокАдресов) OUTER APPLY (SELECT TOP 1 * FROM Событие )
6 май 15, 16:28    [17608390]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4974
o-o
select c.yy, c.mm, a.Address, f.Event
from @Calendar c cross join all_addr a
     left join @FactEvents f on c.yy = f.yy and c.mm = f.mm and a.Address = f.Address;


Мы с о-о одинаково мыслим, только он InMemory не любит
6 май 15, 16:29    [17608402]     Ответить | Цитировать Сообщить модератору
 Re: Сложная выборка из двух таблиц  [new]
o-o
Guest
+ to a_voronin

с тем, кого я не люблю, небольшая промашка вышла,
до InMemory просто руки не дошли, не люблю начинать новое, не покончив со старым,
а у меня и по 2008 R2 пробелов выше крыши
6 май 15, 16:39    [17608497]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить