Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
alexFV Member Откуда: Сообщений: 331 |
Здравствуйте! Подскажите, пожалуйста. Есть 2 таблицы: FactEvents (События.Факт) и PlanEvents (События.План). Столбцы: Address (адрес), Year (год), Month (месяц), Event (событие) Для объяснения задачи возьмем следующие данные: FactEvents
PlanEvents
В результате запроса (запросов) нужно увидеть информацию по каждому адресу в разрезе всего года. Если есть информация для нужного месяца в табл. FactEvents, то берем информацию о событии оттуда. Если нет, но есть в PlanEvents, то берем из нее. Если нет и там и там, то нужно найти ближайшее крайнее значение (при равенстве предпочтение FactEvents). Т.е. для примера выше должно получиться: Result
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
6 май 15, 09:01 [17605446] Ответить | Цитировать Сообщить модератору |
Glory Member Откуда: Сообщений: 104760 |
Нужна 3я таблица - со всеми комбинациями годов и месяцев И станет все просто |
6 май 15, 09:06 [17605471] Ответить | Цитировать Сообщить модератору |
alexFV Member Откуда: Сообщений: 331 |
Спасибо большое. Таблицу можно ввести. Но как станет просто не очень ясно. Не могли бы Вы чуть подробнее объяснить? |
||
6 май 15, 09:18 [17605519] Ответить | Цитировать Сообщить модератору |
Glory Member Откуда: Сообщений: 104760 |
Просто будет потому, что для каждой записи календаря нужно будет просто искать одну ближайшую/равную запись из FactEvents/PlanEvents |
||
6 май 15, 09:32 [17605588] Ответить | Цитировать Сообщить модератору |
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] Ответить | Цитировать Сообщить модератору |
alexFV Member Откуда: Сообщений: 331 |
Спасибо. Но вроде не одну запись для календаря надо искать. Т.к. адресов много. Причем их кол-во может быть разное из месяца в месяц. А можно привести примерную идею запроса? |
||
6 май 15, 11:24 [17606205] Ответить | Цитировать Сообщить модератору |
alexFV Member Откуда: Сообщений: 331 |
Спасибо, LexusR. Получается не надо вводить доп. таблицу если делаем за целый год выборку. А если надо будет не за год брать данные, а за произвольный период, то тогда такой механизм не сработает, верно? Необходимо будет все-таки вводить таблицу комбинаций годов и месяцев, правильно? |
6 май 15, 11:33 [17606272] Ответить | Цитировать Сообщить модератору |
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] Ответить | Цитировать Сообщить модератору |
alexFV Member Откуда: Сообщений: 331 |
LexusR, спасибо! Но честно сказать сложно для меня. Решил попробовать полегче вариант, с календарем. Но тут же столкнулся с проблемой, даже на легкой задаче. Создал таблицу Calendar
И ест таблица FactEvents
Хочу получить объединение, с заполненным событием, если оно есть Result
Подскажите, пожалуйста, с запросом. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
6 май 15, 16:05 [17608201] Ответить | Цитировать Сообщить модератору |
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] Ответить | Цитировать Сообщить модератору |
a_voronin Member Откуда: Москва Сообщений: 4807 |
alexFV, Какой-то из таких вариантов вам наверное нужен (Календарь CROSS JOIN СписокАдресов) LEFT JOIN Событие (Календарь CROSS JOIN СписокАдресов) OUTER APPLY (SELECT TOP 1 * FROM Событие ) |
6 май 15, 16:28 [17608390] Ответить | Цитировать Сообщить модератору |
a_voronin Member Откуда: Москва Сообщений: 4807 |
Мы с о-о одинаково мыслим, только он InMemory не любит |
||
6 май 15, 16:29 [17608402] Ответить | Цитировать Сообщить модератору |
o-o
Guest |
|
|
6 май 15, 16:39 [17608497] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |