SQL Server 2008-如何查找前10个表并对其排序
嗨,我有以下脚本:SQL Server 2008-如何查找前10个表并对其排序,sql,sql-server,Sql,Sql Server,嗨,我有以下脚本: DECLARE @sql VARCHAR(2000); DECLARE @tableName SYSNAME; DECLARE @columnName SYSNAME; DECLARE @count INT; DECLARE @NotCursor TABLE(ID INT IDENTITY(1, 1), TableName SYSNAME, ColumnName SYSNAME) DECLARE
DECLARE @sql VARCHAR(2000);
DECLARE @tableName SYSNAME;
DECLARE @columnName SYSNAME;
DECLARE @count INT;
DECLARE @NotCursor TABLE(ID INT IDENTITY(1, 1),
TableName SYSNAME,
ColumnName SYSNAME)
DECLARE @StartLoop INT
DECLARE @EndLoop INT
DECLARE @SQLFinalQuery VARCHAR(MAX)
INSERT INTO @NotCursor
SELECT TABLE_NAME,
COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
(DATA_TYPE = 'date'
OR DATA_TYPE = 'datetime')
AND table_name NOT LIKE '%[_]%'
ORDER BY TABLE_NAME
SELECT @StartLoop = MIN(ID),
@EndLoop = MAX(ID)
FROM @NotCursor
SET @SQLFinalQuery = ';WITH cte_Resultset AS'+CHAR(13)+CHAR(10)
+'('
WHILE @StartLoop <= @EndLoop
BEGIN
SELECT @tableName = TableName,
@columnName = ColumnName
FROM @NotCursor
WHERE ID = @StartLoop
SET @sql = 'SELECT ''' + @tableName + ''' as [TableName], ' + '''' + @columnName + ''' AS [ColumnName], ' + 'DATEPART(yy, ' + QUOTENAME(@columnName) + ') AS [Year], COUNT(1) AS [NumberofRows]'+CHAR(13)+CHAR(10)
+'FROM ' + QUOTENAME(@tableName) +CHAR(13)+CHAR(10)
+'GROUP BY DATEPART(yy, ' + QUOTENAME(@columnName) + ')';
SET @SQLFinalQuery = @SQLFinalQuery+CHAR(13)+CHAR(10)+@sql;
SET @SQLFinalQuery = CASE
WHEN @StartLoop = @EndLoop THEN @SQLFinalQuery+CHAR(13)+CHAR(10)+')'
ELSE @SQLFinalQuery+CHAR(13)+CHAR(10)+'UNION ALL'
END
SET @StartLoop = @StartLoop + 1
END
SET @SQLFinalQuery = @SQLFinalQuery +'SELECT TOP 10 SUM(NumberofRows) AS NumberOfRows,TableName,ColumnName,Year'+CHAR(13)+CHAR(10)
+'FROM cte_Resultset'+CHAR(13)+CHAR(10)
+'WHERE Year IS NOT NULL'+CHAR(13)+CHAR(10)
+'GROUP BY TableName, ColumnName, Year'+CHAR(13)+CHAR(10)
+'ORDER BY SUM(NumberofRows) DESC'+CHAR(13)+CHAR(10)
EXEC (@SQLFinalQuery)
只需在表变量中收集结果,然后从该表中选择:
DECLARE @sql varchar(2000);
DECLARE @tableName sysname;
DECLARE @columnName sysname;
DECLARE @count int;
DECLARE theCursor CURSOR FOR
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
(DATA_TYPE = 'date' or DATA_TYPE = 'datetime')
and table_name not like '%[_]%'
ORDER BY TABLE_NAME
OPEN theCursor;
FETCH NEXT FROM theCursor INTO @tableName, @columnName;
DECLARE @tables TABLE (TableName nvarchar(128), ColumnName nvarchar(128),
Year int, NumberofRows int)
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = 'SELECT ''' + @tableName + ''' as [TabelName], ' +
'''' + @columnName + ''' AS [ColumnName], ' +
'DATEPART(yy, ' + QUOTENAME(@columnName) +
') AS [Year], COUNT(1) AS [NumberofRows] FROM ' + QUOTENAME(@tableName) +
' GROUP BY DATEPART(yy, ' + QUOTENAME(@columnName) + ')';
PRINT @sql;
INSERT INTO @tables
EXEC (@sql);
FETCH NEXT FROM theCursor INTO @tableName, @columnName;
END
SELECT TOP 10 SUM(NumberofRows) NumberOfRows, tableName, Year FROM @tables GROUP BY TableName, Year ORDER BY SUM(NumberofRows) DESC
CLOSE theCursor
DEALLOCATE theCursor;
基于OP希望获得所有表的计数的更新注释,而不仅仅是最大的10个计数,这可以在没有循环的情况下完成
declare @SQL nvarchar(max)
select @SQL =
STUFF((
select top 20 'SELECT ''' + TABLE_NAME + ''' as [TableName], ' +
'''' + COLUMN_NAME + ''' AS [ColumnName], ' +
'DATEPART(yy, ' + QUOTENAME(COLUMN_NAME) +
') AS [Year], COUNT(1) AS [NumberofRows] FROM ' + QUOTENAME(TABLE_NAME) +
' GROUP BY DATEPART(yy, ' + QUOTENAME(COLUMN_NAME) + ') union all '
from INFORMATION_SCHEMA.COLUMNS
WHERE
(DATA_TYPE = 'date' or DATA_TYPE = 'datetime')
and table_name not like '%[_]%'
ORDER BY TABLE_NAME
for xml path('')),1 , 0 , '')
select @SQL = stuff(@SQL, len(@SQL) - 9, 10, '') + ' order by NumberOfRows desc'
exec sp_executesql @SQL
@用户3712641,这个答案与来自 当我能够回答时,原来的线程已作为副本关闭。然而,由于我已经花了一些时间来优化这个查询,我将继续添加到这篇文章中 我所做的是删除循环插入并消除游标。在本地机器上的测试表明性能有所提高。请尝试让我知道它是否适合你
DECLARE @sql VARCHAR(2000);
DECLARE @tableName SYSNAME;
DECLARE @columnName SYSNAME;
DECLARE @count INT;
DECLARE @NotCursor TABLE(ID INT IDENTITY(1, 1),
TableName SYSNAME,
ColumnName SYSNAME)
DECLARE @StartLoop INT
DECLARE @EndLoop INT
DECLARE @SQLFinalQuery VARCHAR(MAX)
INSERT INTO @NotCursor
SELECT TABLE_NAME,
COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
(DATA_TYPE = 'date'
OR DATA_TYPE = 'datetime')
AND table_name NOT LIKE '%[_]%'
ORDER BY TABLE_NAME
SELECT @StartLoop = MIN(ID),
@EndLoop = MAX(ID)
FROM @NotCursor
SET @SQLFinalQuery = ';WITH cte_Resultset AS'+CHAR(13)+CHAR(10)
+'('
WHILE @StartLoop <= @EndLoop
BEGIN
SELECT @tableName = TableName,
@columnName = ColumnName
FROM @NotCursor
WHERE ID = @StartLoop
SET @sql = 'SELECT ''' + @tableName + ''' as [TableName], ' + '''' + @columnName + ''' AS [ColumnName], ' + 'DATEPART(yy, ' + QUOTENAME(@columnName) + ') AS [Year], COUNT(1) AS [NumberofRows]'+CHAR(13)+CHAR(10)
+'FROM ' + QUOTENAME(@tableName) +CHAR(13)+CHAR(10)
+'GROUP BY DATEPART(yy, ' + QUOTENAME(@columnName) + ')';
SET @SQLFinalQuery = @SQLFinalQuery+CHAR(13)+CHAR(10)+@sql;
SET @SQLFinalQuery = CASE
WHEN @StartLoop = @EndLoop THEN @SQLFinalQuery+CHAR(13)+CHAR(10)+')'
ELSE @SQLFinalQuery+CHAR(13)+CHAR(10)+'UNION ALL'
END
SET @StartLoop = @StartLoop + 1
END
SET @SQLFinalQuery = @SQLFinalQuery +'SELECT TOP 10 SUM(NumberofRows) AS NumberOfRows,TableName,Year'+CHAR(13)+CHAR(10)
+'FROM cte_Resultset'+CHAR(13)+CHAR(10)
+'GROUP BY TableName, Year'+CHAR(13)+CHAR(10)
+'ORDER BY SUM(NumberofRows) DESC'+CHAR(13)+CHAR(10)
EXEC (@SQLFinalQuery)
出于好奇,它是否必须通过代码,或者您不能使用SSMS中内置的
磁盘使用情况表
报告?我更希望通过代码来实现,因为当我运行脚本时,我希望能够看到SQL Server结果窗口中显示的前10个表。这样它就可以被多人使用。所以我知道列名在最终结果中并不重要。这是一个多么奇怪的要求。不太确定这是在做什么,但似乎您正在尝试从任何表中获取前10个datetime列?你为什么要用光标来做这个?不,不是,我只是把它放在那里,看看哪些行与哪个列相关,但不,这并不重要。它看起来工作得很好,呈现的方式也很干净。太好了,谢谢!我一点也不喜欢这里的游标方法,但是如果你喜欢,你应该在里面添加一个计数器,这样一旦table变量有10行,你就可以退出循环。否则,您只需继续运行最终查询将忽略的sql。我将提出一种更基于集合的方法,在没有游标的情况下也可以做同样的事情。声明@RowCountMax int=1。然后使用第二个条件修改While(并且@RowCountMax<10)。最后,在执行动态sql之后立即添加此项(set@RowCountMax=@@ROWCOUNT)。这至少会迫使循环在得到10行之后退出。好的,Sean,但是我们不知道前10个表,除非我们遍历所有表并计算匹配的行。您的建议使代码只返回按名称排序的前10个表。现在,您从前10个表开始,没有必要得到更多。然后将循环中的行数限制为10,因为这就是您要选择的所有行数。您好,感谢您的回复!它确实似乎工作得更好,并且提供了与以前相同的信息。看起来不错,谢谢你的帮助。很高兴它对你有用。嗨,我更新了我的问题,我忘了我也想在输出中有列名,但似乎无法让它工作,你能帮我一下吗?@user3712641,我已按要求将列添加到结果集中。效果很好,再次感谢你。我想当我试图在我的代码上修改它时,它要困难得多,但是使用您提供的代码要容易得多。
DECLARE @sql VARCHAR(2000);
DECLARE @tableName SYSNAME;
DECLARE @columnName SYSNAME;
DECLARE @count INT;
DECLARE @NotCursor TABLE(ID INT IDENTITY(1, 1),
TableName SYSNAME,
ColumnName SYSNAME)
DECLARE @StartLoop INT
DECLARE @EndLoop INT
DECLARE @SQLFinalQuery VARCHAR(MAX)
INSERT INTO @NotCursor
SELECT TABLE_NAME,
COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
(DATA_TYPE = 'date'
OR DATA_TYPE = 'datetime')
AND table_name NOT LIKE '%[_]%'
ORDER BY TABLE_NAME
SELECT @StartLoop = MIN(ID),
@EndLoop = MAX(ID)
FROM @NotCursor
SET @SQLFinalQuery = ';WITH cte_Resultset AS'+CHAR(13)+CHAR(10)
+'('
WHILE @StartLoop <= @EndLoop
BEGIN
SELECT @tableName = TableName,
@columnName = ColumnName
FROM @NotCursor
WHERE ID = @StartLoop
SET @sql = 'SELECT ''' + @tableName + ''' as [TableName], ' + '''' + @columnName + ''' AS [ColumnName], ' + 'DATEPART(yy, ' + QUOTENAME(@columnName) + ') AS [Year], COUNT(1) AS [NumberofRows]'+CHAR(13)+CHAR(10)
+'FROM ' + QUOTENAME(@tableName) +CHAR(13)+CHAR(10)
+'GROUP BY DATEPART(yy, ' + QUOTENAME(@columnName) + ')';
SET @SQLFinalQuery = @SQLFinalQuery+CHAR(13)+CHAR(10)+@sql;
SET @SQLFinalQuery = CASE
WHEN @StartLoop = @EndLoop THEN @SQLFinalQuery+CHAR(13)+CHAR(10)+')'
ELSE @SQLFinalQuery+CHAR(13)+CHAR(10)+'UNION ALL'
END
SET @StartLoop = @StartLoop + 1
END
SET @SQLFinalQuery = @SQLFinalQuery +'SELECT TOP 10 SUM(NumberofRows) AS NumberOfRows,TableName,Year'+CHAR(13)+CHAR(10)
+'FROM cte_Resultset'+CHAR(13)+CHAR(10)
+'GROUP BY TableName, Year'+CHAR(13)+CHAR(10)
+'ORDER BY SUM(NumberofRows) DESC'+CHAR(13)+CHAR(10)
EXEC (@SQLFinalQuery)
SET @SQLFinalQuery = @SQLFinalQuery +'SELECT TOP 10 SUM(NumberofRows) AS NumberOfRows,TableName,ColumnName,Year'+CHAR(13)+CHAR(10)
+'FROM cte_Resultset'+CHAR(13)+CHAR(10)
+'GROUP BY TableName, ColumnName, Year'+CHAR(13)+CHAR(10)
+'ORDER BY SUM(NumberofRows) DESC'+CHAR(13)+CHAR(10)
EXEC (@SQLFinalQuery)