0

我有许多表(大约 40 个)包含大约 4000 万辆汽车的快照数据。每个快照表都位于特定时间点(季度末),并且在结构上是相同的。

虽然我们的大部分分析都是针对单个快照,但有时我们需要同时针对所有快照运行一些分析。例如,我们可能需要构建一个新表,其中包含每个快照中的所有福特福克斯汽车。

为了实现这一点,我们目前有两种选择:
a) 编写一个很长很长的批处理文件,一遍又一遍地重复相同的代码,只需更改 FROM 子句
[缺点 - 编写和更改单行代码需要很长时间其中一个块中的代码需要在所有其他块中进行细微的更改]
b) 使用视图将所有表联合在一起并查询
[缺点 - 我们的表存储在单独的数据库实例中并且不能被索引,加上结果视图是大约 6 亿条记录长 x 125 列宽,所以速度非常慢]

所以,我想知道我是否可以使用动态 sql 或将 SQL 放入循环中以假脱机处理所有表。这将是这样的:

for each *table* in TableList
INSERT INTO output_table
SELECT *table* as OriginTableName, Make, Model
FROM *table*
next *table* in TableList

这可能吗?这意味着当我们的客户端更改他们需要的内容时更新原始 SQL(非常经常发生!)将非常简单,并且我们将从原始表上已有的所有索引中受益。

任何指示、建议或帮助将不胜感激。

4

2 回答 2

3

如果您可以识别您的表(例如命名模式),您可以简单地说:

DECLARE @sql NVARCHAR(MAX);

SELECT @sql = N'';

SELECT @sql = @sql + 'INSERT output_table SELECT ''' + name + ''', Make, Model
    FROM dbo.' + QUOTENAME(name) + ';'
FROM sys.tables 
WHERE name LIKE 'pattern%';
-- or WHERE name IN ('t1', 't2', ... , 't40');

EXEC sp_executesql @sql;

这假设它们都在dbo模式中。如果不是,调整很容易......只需替换dbo' + QUOTENAME(SCHEMA_NAME([schema_id])) + '......

于 2012-04-16T15:06:03.133 回答
0

最后我使用了两种方法:
另一个论坛上有人建议使用 sp_msforeachtable 和一个包含所有表名的表。他们的建议是:

create table dbo.OutputTable (OriginTableName nvarchar(500), RecordCount INT)
create table dbo.TableList (Name nvarchar (500))

insert dbo.TableList 
        select '[dbo].[swap]'
union   select '[dbo].[products]'
union   select '[dbo].[structures]'
union   select '[dbo].[stagingdata]'

exec sp_msforeachtable @command1 = 'INSERT INTO dbo.OutputTable SELECT ''?'',    COUNT(*)     from ?'
,@whereand = 'and syso.object_id in (select object_id(Name) from dbo.TableList)'             

select * from dbo.OutputTable

这对于某些查询非常有效,但似乎无法在查询中使用 GROUP BY 子句这一事实(或者,至少,我找不到这样做的方法)。

我使用的最终解决方案是将 Dynamic SQL 与包含表名的查找表一起使用。在一个非常简单的形式中,这看起来像:

DECLARE @TableName varchar(500)
DECLARE @curTable CURSOR
DECLARE @sql NVARCHAR(1000)

SET @curTable = CURSOR FOR 
SELECT [Name] FROM Vehicles_LookupTables.dbo.AllStockTableList

OPEN @curTable
FETCH NEXT
FROM @curTable INTO @TableName

WHILE @@FETCH_STATUS = 0
BEGIN

SET @sql = 'SELECT ''' +@TableName + ''', Make, sum(1) as Total FROM ' + @TableName + ' GROUP BY Make'
EXEC sp_executesql @sql

FETCH NEXT
FROM @curTable INTO @TableName

END
CLOSE @curTable
DEALLOCATE @curTable
于 2012-04-18T07:35:46.760 回答