L oop запрос через несколько таблиц - PullRequest
0 голосов
/ 19 февраля 2020

Я хотел бы получить тот же запрос, который почти никогда не будет возвращать никаких результатов через несколько таблиц. Имя таблицы такое же, за исключением добавления года. Итак, мой запрос выглядит так:

select p.productID, po.name, p.price from prices_2001  p
join products po on p.productID = po.id
where price < 0

, и я хотел бы l oop в течение всех лет, с 2001 по 2020 год. Поэтому он должен выглядеть так:

select p.productID, po.name, p.price from prices_2001  p
join products po on p.productID = po.id
where price < 0

select p.productID, po.name, p.price from prices_2002  p
join products po on p.productID = po.id
where price < 0

select p.productID, po.name, p.price from prices_2003  p    --Looping trough all the tables until 2020
join products po on p.productID = po.id
where price < 0

Если есть результаты, они могут быть сохранены во временной таблице. Я думал о создании al oop с именами таблиц или создании динамического c sql запроса. Какова лучшая практика и как я могу использовать этот запрос для всех таблиц, просто выполнив его один раз?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 19 февраля 2020

Чтобы повторить мой комментарий:

Это звучит как проблема денормализации, на самом деле у вас должна быть 1 таблица со столбцом для года.

На самом деле, вы должны исправить свой дизайн.

В любом случае, на проблему: вы можете сделать это с Dynami c SQL, да, но вы бы лучше исправить дизайн. Это, однако, создает и выполняет инструкцию динамически. я использовал FOR XML PATH из-за отсутствия тега версии:

DECLARE @SQL nvarchar(MAX),
        @CRLF nchar(2) = NCHAR(13) + NCHAR(10);


SET @SQL = STUFF((SELECT @CRLF + N'UNION ALL' + @CRLF +
                         N'SELECT p.productID, po.name, p.price' + @CRLF +
                         N'FROM ' + QUOTENAME(t.[name]) + N'p' + @CRLF +
                         N'     JOIN product po ON p.productID = po.id' + @CRLF +
                         N'WHERE p.price < 0'
                  FROM sys.tables t
                  WHERE t.[name] LIKE N'prices[_]20[0-9][0-9]'
                  ORDER BY t.[name]
                  FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,13,N'') + N';';

--PRINT @SQL; --Your debugging friend

EXEC sys.sp_executesql @SQL;
1 голос
/ 19 февраля 2020

Это сложно и дорого (зацикливание оператора SQL!), Потому что ваша схема плохая. Вместо этого у вас должна быть одна таблица prices, которая идентична вашим существующим таблицам, но имеет один дополнительный столбец с именем year. Тогда объединение становится простым, и вам не нужно создавать новые таблицы только потому, что дата изменилась.

Вместо этого вы можете ОБЪЕДИНИТЬ свои таблицы вместе и получить то же самое. Что-то вроде:

SELECT p.productID, po.name, p.price, po.year
FROM products p
     INNER JOIN 
         (
              SELECT id, name, 2001 as year FROM prices_2001
              UNION ALL SELECT id, name, 2002 FROM prices_2002
              UNION ALL SELECT id, name, 2003 FROM prices_2003
              UNION ALL ... <continue until you have all year tables accounted for>
         ) po
         ON p.productID = po.id
WHERE po.price < 0;

Попробуйте записать результаты этого подзапроса UNION в новую таблицу и просто использовать его с этого момента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...