Create a variable from a table and pass it through another table - sql

Here is my sql:
if object_id('tempdb..#COLUMN_NAMES') is not null
drop table #COLUMN_NAMES
SELECT COLUMN_NAME AS Column_Names
INTO #COLUMN_NAMES
FROM information_schema.columns
WHERE table_name = 'ssrs_sourcedata'
----- select * from #COLUMN_NAMES ----
if object_id('tempdb..#DATA_QUALITY_CHECK') is not null
drop table #DATA_QUALITY_CHECK
SELECT
periodenddate,
'#Column_Name' AS Label,
MIN(#Column_Name) AS Min_Value,
MAX(#Column_Name) AS Max_Value,
SUM(#Column_Name) AS Sum_Value,
AVG(#Column_Name) AS Avg_Value,
SUM(Case when #Column_Name IS NULL THEN 1 ELSE 0 END) AS Null_Count,
SUM(Case when len(cast(#Column_Name AS VARCHAR)) = 0 THEN 1 ELSE 0 END) AS
Space_Count,
MAX(len(cast(#Column_Name AS VARCHAR))) AS max_length,
MIN(len(cast(#Column_Name AS VARCHAR))) AS min_length
INTO #DATA_QUALITY_CHECK
FROM dbcrms.report.ssrs_sourcedata WHERE periodenddate = '2017-06-30'
GROUP BY periodenddate
How do I create a variable from the table #column_names and pass it through the data quality check table and store the results in the data quality check table. Also how do I get the sql to read the first column until the last column. There are 51 records in the #column_names table.

DECLARE #Column_Name TABLE
(
Column_Name varchar(500)
)
INSERT INTO #Column_Name (Column_Name)
SELECT COLUMN_NAME AS Column_Names
FROM information_schema.columns
WHERE table_name = 'ssrs_sourcedata'
You can now use this table in your query.

You can use curosr as follows:
DECLARE #Column_Name varchar(255)
DECLARE #SQL VARCHAR(MAX)
create table ##DATA_QUALITY_CHECK
(
Label varchar(255),
Min_Value int,
Max_Value int,
Sum_Value int,
Avg_Value int,
Null_Count int,
max_length int,
min_length int
)
DECLARE COLUMN_NAME_CURSOR CURSOR
FOR
SELECT COLUMN_NAMES
FROM #COLUMN_NAMES
OPEN COLUMN_NAME_CURSOR
FETCH NEXT FROM COLUMN_NAME_CURSOR INTO #Column_Name
WHILE ##FETCH_STATUS = 0
BEGIN
select #sql = 'INSERT INTO ##DATA_QUALITY_CHECK
SELECT
periodenddate,
' + #Column_Name + ' AS Label,
MIN(' + #Column_Name + ') AS Min_Value,
MAX(' + #Column_Name + ') AS Max_Value,
SUM(' + #Column_Name + ') AS Sum_Value,
AVG(' + #Column_Name + ') AS Avg_Value,
SUM(Case when ' + #Column_Name + ' IS NULL THEN 1 ELSE 0 END) AS Null_Count,
SUM(Case when len(cast(' + #Column_Name + ' AS VARCHAR)) = 0 THEN 1 ELSE 0 END) AS
Space_Count,
MAX(len(cast(' + #Column_Name + ' AS VARCHAR))) AS max_length,
MIN(len(cast(' + #Column_Name + ' AS VARCHAR))) AS min_length
FROM dbcrms.report.ssrs_sourcedata WHERE periodenddate = ''2017-06-30''
GROUP BY periodenddate '
--print #sql
exec(#SQL)
FETCH NEXT FROM COLUMN_NAME_CURSOR INTO #Column_Name
END
CLOSE COLUMN_NAME_CURSOR
DEALLOCATE COLUMN_NAME_CURSOR

Related

Creating a column loop within a table loop to calculate fill rate for all fields in a database

I have 2 databases with over 400 tables for which I have to calculate fill rates. I have a loop for calculating fill rates for all columns in a table, but how can I do it for all tables in a database?? Please help!
I am using SQL Server.
Here is the code for looping through all columns in a table for calculating fill rate-
DECLARE #Table NVARCHAR(max) = 'dbo.[TableName]'
,#MetaTable NVARCHAR(128) = '#TempTable'
,#ColumnName NVARCHAR(128)
,#Iterator INT = 1
,#SQL1 NVARCHAR(MAX)
SELECT c.NAME
,c.COLUMN_ID
,ROW_NUMBER() OVER (ORDER BY COLUMN_ID) AS RN
INTO #Cols
FROM SYS.COLUMNS c
WHERE c.OBJECT_ID = OBJECT_ID(#Table);
WHILE #Iterator <= (SELECT ISNULL(MAX(RN),0) FROM #Cols)
BEGIN
SET #ColumnName = (SELECT NAME FROM #Cols WHERE RN = #Iterator)
SET #SQL1 = 'INSERT INTO ' + #MetaTable + ' (Table_Name, Column_Name,
Fill_Rate) '
+ 'SELECT ''' + REPLACE(#Table,'DBO.','') + ''', ''' +
#ColumnName + ''', 100 * CONVERT(DECIMAL(8,3), SUM(CASE WHEN [' +
#ColumnName + '] IS NULL THEN 0 ELSE 1 END)) / COUNT(1) AS [' +
#ColumnName + '_fill]' + ' FROM ' + #Table
EXEC sp_executesql #SQL1
SET #Iterator += 1
END
I suggest to use a cursor for this neat little task:
CREATE TABLE #MetaTable (
TABLE_SCHEMA sysname,
TABLE_NAME sysname,
COLUMN_NAME sysname,
fill_rate float NULL);
DECLARE
#schema sysname,
#table sysname,
#column sysname,
#sql nvarchar(max);
DECLARE column_cusor CURSOR FAST_FORWARD FOR
SELECT s.name, t.name, c.name
FROM sys.schemas s
INNER JOIN sys.tables t ON s.schema_id = t.schema_id
INNER JOIN sys.columns c ON t.object_id = c.object_id;
OPEN column_cusor;
FETCH NEXT FROM column_cusor INTO #schema, #table, #column;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'SELECT ' + QUOTENAME(#schema, '''')
+ ', ' + QUOTENAME(#table, '''')
+ ', ' + QUOTENAME(#column, '''')
+ ', ' + '100.0 * SUM(CASE WHEN ' + QUOTENAME(#column)
+ ' IS NULL THEN 0 ELSE 1 END) /'
+ ' CASE WHEN COUNT(*) = 0 THEN 1 ELSE COUNT(*) END'
+ ' FROM ' + QUOTENAME(#schema) + '.' + QUOTENAME(#table);
INSERT INTO #MetaTable (TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, fill_rate)
EXEC (#sql);
FETCH NEXT FROM column_cusor INTO #schema, #table, #column;
END
CLOSE column_cusor;
DEALLOCATE column_cusor;
SELECT * FROM #MetaTable;

How to build a WHILE Loop using SQL Server 2014

I have loaded the column names from a table into the temporary table called #COLUMN_NAMES. I would like to build a while loop that passes each of the rows from the temp table through my #Data_Quality_Check table that I created below.
There are 54 rows of column_names in my table #Column_names currently. Ideally I would like to have the while loop process each of the variables and put the output into the #Data_Quality_Check table.
if object_id('tempdb..#COLUMN_NAMES') is not null
drop table #COLUMN_NAMES
SELECT COLUMN_NAME AS Column_Names
INTO #COLUMN_NAMES
FROM information_schema.columns
WHERE table_name = 'ssrs_sourcedata'
----- >>>> !!!!!! INSERT CODE TO BUILD WHILE LOOP !!!!
if object_id('tempdb..#DATA_QUALITY_CHECK') is not null
drop table #DATA_QUALITY_CHECK
SELECT
periodenddate,
'#Column_Name' AS Label,
MIN(#Column_Name) AS Min_Value,
MAX(#Column_Name) AS Max_Value,
SUM(#Column_Name) AS Sum_Value,
AVG(#Column_Name) AS Avg_Value,
SUM(Case when #Column_Name IS NULL THEN 1 ELSE 0 END) AS Null_Count,
SUM(Case when len(cast(#Column_Name AS VARCHAR)) = 0 THEN 1 ELSE 0 END) AS Space_Count,
MAX(len(cast(#Column_Name AS VARCHAR))) AS max_length,
MIN(len(cast(#Column_Name AS VARCHAR))) AS min_length
INTO
#DATA_QUALITY_CHECK
FROM
dbcrms.report.ssrs_sourcedata
WHERE
periodenddate = '2017-06-30'
GROUP BY
periodenddate
Dynamic that badboy. You need to create the empty temp table first though
declare #cnt int = 1;
declare #mcnt int;
declare #vsql varchar(2000);
declare #column_name varchar(100);
select #mcnt = count(*)
from #COLUMN_NAMES;
while #cnt <= #mcnt
begin
select #column_name = column_names
from
(
select column_names, row_number() over(order by column_names) rn
from #COLUMN_NAMES
)
where rn = #cnt;
set #vsql = 'insert into #DATA_QUALITY_CHECK (Label, min_value, max_value, sum_value, avg_value, null_count, space_count, max_length, min_length)
SELECT periodenddate, ''' + #Column_Name + ''' AS Label,
MIN(' + #Column_Name+ ') AS Min_Value,
MAX(' + #Column_Name + ') AS Max_Value,
SUM(' + #Column_Name + ') AS Sum_Value,
AVG(' + #Column_Name + ') AS Avg_Value,
SUM(Case when ' + #Column_Name + ' IS NULL THEN 1 ELSE 0 END) AS Null_Count,
SUM(Case when len(cast(' + #Column_Name + ' AS VARCHAR)) = 0 THEN 1 ELSE 0 END) AS Space_Count,
MAX(len(cast(' + #Column_Name + ' AS VARCHAR))) AS max_length,
MIN(len(cast(' + #Column_Name + ' AS VARCHAR))) AS min_length
FROM dbcrms.report.ssrs_sourcedata WHERE periodenddate = '2017-06-30'
GROUP BY periodenddate ';
execute(#vsql);
set #cnt = #cnt + 1;
end;

null percentage dynamic sql

I have the following sql:
SET NOCOUNT ON
DECLARE #Schema NVARCHAR(100) = 'dbo'
DECLARE #Table NVARCHAR(100) = NULL
DECLARE #sql NVARCHAR(MAX) =''
IF OBJECT_ID ('tempdb..#Nulls') IS NOT NULL
DROP TABLE #Nulls
CREATE TABLE #Nulls
(
TableName sysname,
ColumnName sysname,
ColumnPosition int,
NullCount int,
NonNullCount int
)
select #sql += 'select TableName = ''' + quotename(table_schema) + '.' +
quotename(table_name) + ''' , ColumnName = ''' + quotename(column_name)
+ ''' , ColumnPosition = ''' + convert(varchar(5) , ordinal_position)
+ ''' , CountNulls = sum(case when ' + quotename(column_name) + ' is null
then 1 else 0 end) , CountnonNulls = count(' + quotename(column_name) + ')
from ' + quotename(table_schema) + '.' + quotename(table_name) + ';' + char(10)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = #Schema AND (#Table IS NULL OR TABLE_NAME = #Table)
INSERT INTO #Nulls
EXEC sp_executesql #sql
SELECT *
FROM #Nulls
However, I would like the database name in the first column, the schema name inn the second and not joined like it currently is and lastly at the end column showing total number of null as a percentage?
Thank you
If you want your code to gather data about tables in all databases on the server, you need to iterate over each database separately:
SET NOCOUNT ON
DECLARE #Schema NVARCHAR(100) = 'dbo'
DECLARE #Table NVARCHAR(100) = NULL
DECLARE #sql NVARCHAR(MAX) =''
IF OBJECT_ID ('tempdb..#Nulls') IS NOT NULL
DROP TABLE #Nulls
CREATE TABLE #Nulls
(
DbName sysname,
SchemaName sysname,
TableName sysname,
ColumnName sysname,
ColumnPosition int,
NullCount int,
NonNullCount int
)
;
DECLARE #db_name VARCHAR(50) -- database name
DECLARE db_cursor CURSOR FOR
SELECT name
FROM msdb.sys.databases
-- Iterate over all databases, except for these
WHERE name NOT IN ('master','model','msdb','tempdb')
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #db_name
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'USE ' + QUOTENAME(#db_name)
EXEC sp_executesql #sql
select #sql += 'select DbName = ''' + quotename(#db_name)
+ ''', SchemaName = ''' + quotename(table_schema)
+ ''', TableName = ''' + quotename(table_schema) + '.' + quotename(table_name)
+ ''' , ColumnName = ''' + quotename(column_name)
+ ''' , ColumnPosition = ''' + convert(varchar(5) , ordinal_position)
+ ''' , CountNulls = sum(case when ' + quotename(column_name) + ' is null
then 1 else 0 end) , CountnonNulls = count(' + quotename(column_name) + ')
from ' + quotename(table_schema) + '.' + quotename(table_name) + ';' + char(10)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (#Table IS NULL OR TABLE_NAME = #Table)
INSERT INTO #Nulls
EXEC sp_executesql #sql
FETCH NEXT FROM db_cursor INTO #db_name
END
CLOSE db_cursor
DEALLOCATE db_cursor
SELECT *
FROM #Nulls
SET NOCOUNT ON
DECLARE #Schema NVARCHAR(100) = 'dbo'
DECLARE #Table NVARCHAR(100) = NULL
DECLARE #sql NVARCHAR(MAX) =''
IF OBJECT_ID ('tempdb..#Nulls') IS NOT NULL DROP TABLE #Nulls
CREATE TABLE #Nulls (DataBaseName sysname,SchemaName sysname,TableName sysname, ColumnName sysname,
ColumnPosition int
, NullCount int , NonNullCount int)
--select * from INFORMATION_SCHEMA.COLUMNS
select #sql += 'select DBName = '''+ quotename(TABLE_CATALOG)
+''',SchemaName = '''+ quotename(table_schema) +''',TableName = '''
+ quotename(table_name) + ''' , ColumnName = ''' + quotename(column_name)
+ ''' , ColumnPosition = ''' + convert(varchar(5) , ordinal_position)
+ ''' , CountNulls = sum(case when ' + quotename(column_name) + ' is null
then 1 else 0 end) , CountnonNulls = count(' + quotename(column_name) + ')
from ' + quotename(table_schema) + '.' + quotename(table_name) + ';' + char(10)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = #Schema AND (#Table IS NULL OR TABLE_NAME = #Table)
INSERT INTO #Nulls
EXEC sp_executesql #sql
SELECT *,NullCntPercentage = (case when isnull(NullCount,0)=0 then 0 else cast((NullCount*100.0/(NullCount+NonNullCount)) as decimal(15,2)) end)
,NonNullCntPercentage = (case when NonNullCount=0 then 0 else cast((NonNullCount*100.0/(NullCount+NonNullCount)) as decimal(15,2)) end)
FROM #Nulls order by TableName,ColumnPosition
Below is the output
DataBaseName SchemaName TableName ColumnName ColumnPosition NullCount NonNullCount NullCntPercentage NonNullCntPercentage
[MyDB] [dbo] [EmpDtl1] [EmpId] 1 1 6 14.29 85.71
[MyDB] [dbo] [EmpDtl1] [EmpName] 2 1 6 14.29 85.71

dynamic sql with datekey

I have the following SQL, however I would like to add a date key to this but been struggling: SQL as follows
SET NOCOUNT ON
DECLARE #Schema NVARCHAR(100) = 'dbo'
DECLARE #Table NVARCHAR(100) = NULL
DECLARE #sql NVARCHAR(MAX) =''
IF OBJECT_ID ('tempdb..#Nulls') IS NOT NULL DROP TABLE #Nulls
CREATE TABLE #Nulls (DataBaseName sysname,SchemaName sysname,TableName sysname, ColumnName sysname,
ColumnPosition int
, NullCount int , NonNullCount int)
select #sql += 'select DBName = '''+ quotename(TABLE_CATALOG)
+''',SchemaName = '''+ quotename(table_schema) +''',TableName = '''
+ quotename(table_name) + ''' , ColumnName = ''' + quotename(column_name)
+ ''' , ColumnPosition = ''' + convert(varchar(5) , ordinal_position)
+ ''' , CountNulls = sum(case when ' + quotename(column_name) + ' is null
then 1 else 0 end) , CountnonNulls = count(' + quotename(column_name) + ')
from ' + quotename(table_schema) + '.' + quotename(table_name) + ';' + char(10)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = #Schema AND (#Table IS NULL OR TABLE_NAME = #Table)
INSERT INTO #Nulls
EXEC sp_executesql #sql
SELECT *,NullCntPercentage = (case when isnull(NullCount,0)=0 then 0 else cast((NullCount*100.0/(NullCount+NonNullCount)) as decimal(15,2)) end)
,NonNullCntPercentage = (case when NonNullCount=0 then 0 else cast((NonNullCount*100.0/(NullCount+NonNullCount)) as decimal(15,2)) end)
FROM #Nulls order by TableName,ColumnPosition
I would like to add the date key using the following
convert(nvarchar(11),getdate(),112)
But been struggling to add this to dynamic sql and not in the output in the second stage which does the percentage
Thank you

SQL Server 2008 - How to find top 10 tables and order them

Hi I have the following script:
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)
The output of this script provides me with the NumberofRows, TableName, ColumnName, and Year.
However, I also want to additionally filter the results. Currently, the script searches through every table without "_" in it. But, I also want it to also only look at the tables which are related to a calendar (the table must be joint to a calendar). The table where the table name and calendar name can be found is called TimeDependencies. Is there any way to join my current code and this table, so that the result of the script will filter out tables which dont have an associated calendar with them?
Thanks.
Sample Data:
T002 dtCodeObjective
T002 dtDCNandPersistency
T002 dtServiceFee
T004 dtMilitaryCommission
#user3712641,This answer is related to the question from SQL Server 2008 - Optimizing Select statement [duplicate]
By the time I could answer, the original thread was closed as a duplicate. However as I had already put some time into optimize this query, I am going ahead and adding to this post instead.
What I did is remove looped inserts and eliminated cursors. Tests on local machine showed some performance increment. Please try and let me know if it works for you.
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)
IF you need to include Columns, Please replace the last 6 line with this
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)
Just gather the results inside a table variable and select from that table:
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;
Based on the updated comments that the OP wants to get the counts for all tables, not just the 10 largest counts this can be done with no loops.
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