通过多个表循环查询

Loop query through multiple tables

我想要同一个查询,它几乎不会 return 通过多个 table 获得任何结果。 table 名称是相同的,只是增加了年份。所以我的查询看起来像这样:

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

我想遍历从 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

如果有结果,可以将它们存储在临时文件中 table。我想用 table 名称创建一个循环或创建动态 sql 查询。最佳做法是什么?如何仅通过执行一次就将此查询用于所有 table?

谢谢!

这很困难且代价高昂(循环 SQL 语句!)因为您的模式很糟糕。相反,您应该有一个与现有 table 相同的 table prices,但多了一个名为 year 的列。然后加入就变得简单了,你不必仅仅因为日期改变就创建新的 tables。

相反,尽管您可以将 table 联合在一起并得到相同的结果。类似于:

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 子查询的结果写入新的 table,并从现在开始使用它。

重申我的评论:

This sounds like a denormalisation problem, really you should have 1 table with a column for the year.

真的,你应该修复你的设计。

无论如何,进入问题:你可以用动态 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;