How to get count across multiple tables - sql

I am using this code to get ABC count from all tables having 72 table
if I use
declare #SQL nvarchar(max)
declare #Countt bigint
SELECT #SQL = STUFF(( SELECT ' ; SELECT COUNT(ABC) FROM ' + INFORMATION_SCHEMA.TABLES.TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES LEFT OUTER JOIN INFORMATION_SCHEMA.COLUMNS ON INFORMATION_SCHEMA.TABLES.TABLE_NAME = INFORMATION_SCHEMA.COLUMNS.TABLE_NAME where INFORMATION_SCHEMA.TABLES.TABLE_TYPE =N'BASE TABLE' AND INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME =N'ABC'
FOR XML PATH('')),1,2,'')
SET #SQL = #SQL
PRINT #SQL
EXECUTE (#SQL)
but I am getting 72 results one by one but I just want to get sum of all 72 results,for example if ABC have 10 rows in 4 Tables so it should be return 40 please suggest where I am wrong or any other better way

Everyone is right just need to add schema if there is different ones:
declare #SQL nvarchar(max)
declare #Countt bigint
SELECT #SQL = STUFF((
SELECT DISTINCT ' UNION ALL SELECT COUNT(ABC) AS CountAmount FROM ' + INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA + '.' + INFORMATION_SCHEMA.TABLES.TABLE_NAME AS [text()]
FROM INFORMATION_SCHEMA.TABLES
LEFT OUTER JOIN INFORMATION_SCHEMA.COLUMNS
ON INFORMATION_SCHEMA.TABLES.TABLE_NAME = INFORMATION_SCHEMA.COLUMNS.TABLE_NAME
WHERE INFORMATION_SCHEMA.TABLES.TABLE_TYPE =N'BASE TABLE'
AND INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME =N'ABC'
FOR XML PATH('')),1,11,'')
SET #SQL = 'SELECT SUM( CountAmount ) AS TotalSum FROM (' + #SQL + ' ) AS T '
PRINT #SQL
EXECUTE (#SQL)

declare #SQL nvarchar(max)
declare #Countt bigint
SELECT #SQL = STUFF(( SELECT ' UNION ALL SELECT COUNT(ABC) AS noCount FROM ' + INFORMATION_SCHEMA.TABLES.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES LEFT OUTER JOIN INFORMATION_SCHEMA.COLUMNS ON INFORMATION_SCHEMA.TABLES.TABLE_NAME = INFORMATION_SCHEMA.COLUMNS.TABLE_NAME where INFORMATION_SCHEMA.TABLES.TABLE_TYPE =N'BASE TABLE' AND INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME =N'ABC' FOR XML PATH('')),1,10,'')
SET #SQL = 'SELECT COUNT(*) FROM (' + #SQL + ')A'
PRINT #SQL
EXECUTE (#SQL)

You need to use an aggregate function and group your results. So if Ive read your sql correctly, group by INFORMATION_SCHEMA.TABLES.TABLE_NAME

Use a cursor and iterate over each table one by one. When you generate your dynamic sql string, select the results into a variable like so:
select #TableCount = Count(ABC) From SomeTable
set #TotalCount = #Totalcount + #TableCount

Related

SQL count distinct or not null for each column for many columns

I need to analyze a large table with hundreds of columns. A lot of columns are unused.
To investigate I could do something like
SELECT DISTINCT Column1
FROM myTable
or
WITH C AS
(
SELECT DISTINCT Column1
FROM MyTable
)
SELECT COUNT(*)
FROM C
Then I do the same for column2 and so on. However these queries only work for one column which is time consuming and does not give overview in one glance.
Any idea how to build such investigation query for all columns in one?
You need only 1 query where you have to list all the columns of the table:
SELECT COUNT(DISTINCT Column1) column1_count,
COUNT(DISTINCT Column2) column2_count,
COUNT(DISTINCT Column3) column3_count
.....................................
FROM MyTable;
For local purposes only, you can make it dynamic like this:
Get the columns of the table
the query is created as the colleagues did and then it is executed with the EXEC()
DECLARE #columns as Table(RowId INT IDENTITY(1,1), ColumnName nVarchar(50))
DECLARE #ii int = 0
DECLARE #max int = 0
DECLARE #sqlQuery nVarchar(MAX)
INSERT INTO #columns
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'Customer'
SET #sqlQuery = 'SELECT '
SELECT #max = COUNT(*) FROM #columns
WHILE #ii <= #max
BEGIN
SELECT #sqlQuery = CONCAT(#sqlQuery,'COUNT(DISTINCT ',ColumnName,') ',LOWER(ColumnName),'_count, ')
FROM #columns
WHERE RowId = #ii
SET #ii = #ii + 1
END
SELECT #sqlQuery = CONCAT(#sqlQuery,'FROM Customer')
SELECT #sqlQuery = REPLACE(#sqlQuery,', FROM',' FROM')
select #sqlQuery
EXEC (#sqlQuery)
You should flesh out your requirement a bit more. If all you want to know is if a column contains only NULLs, you'll want to check for max(ColumnName) is null
declare #sql table (id int identity(1,1), QueryString nvarchar(max))
create table ##emptyColumns (emptyColumn nvarchar(128))
declare #i int = 0
declare #iMax int
declare #runthis nvarchar(max)
insert #sql
select 'select ''' + QUOTENAME(s.name) + '.' + QUOTENAME(o.name) + quotename(c.name) + ''' as ''column''
from ' + QUOTENAME(s.name) + '.' + QUOTENAME(o.name) + '
having max(' + c.name + ') is null'
from sys.sysobjects o
inner join sys.syscolumns c on c.id = o.id
inner join sys.schemas s on s.schema_id = o.uid
where o.type = 'U'
order by s.name
, o.name
, c.colorder
select #iMax = count(*)
from #sql
print #iMax
while #i < #iMax
begin
set #i = #i + 1
select #runthis = 'insert into ##emptyColumns
' + QueryString
from #sql
where id = #i
execute sp_executesql #runthis
end
select *
from ##emptyColumns
drop table ##emptyColumns
One further option you might consider:
declare #sql nvarchar(max)
select #sql = isnull(#sql + ' union all ', '') + 'select ''' + COLUMN_NAME + ''',
sum(case when ' + COLUMN_NAME + ' is null then 1 else 0 end) as null_values,
count(distinct ' + COLUMN_NAME + ') as count_distinct
from ' + TABLE_SCHEMA + '.' + TABLE_NAME + '
'
from information_schema.columns
where TABLE_SCHEMA = 'MySchema' and TABLE_NAME = 'MyTable'
exec (#sql)
If you had very big tables with large numbers of columns and were only interested in empty columns you could look into something like checksum_agg(checksum(column_name)). It may help improve performance.
You'd need to be wary of column data types, as they are not all compatible with distinct.

How to combine multiple results from a loop into one temp table

I have this statement:
Declare #sql varchar(max) = ''
declare #tablename as varchar(255) = 'test'
select #sql = #sql + 'select [' + c.name + '],count(*) as ''' + c.name
+ ''' from [' + t.name + ']'
from sys.columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = #tablename
EXEC (#sql)
But it gives the output comes out in different results windows and when I try to combine it with a union all the text doesn't fit it. I want to try and get the results into a temp table for SQL server is there anyway i can do this?
I'm trying to get:
Column Name Count Distinct Count
a 100 1
b 100 5
c 100 73
d 100 9
The statement above isn't for distinct count but i'm hoping I could replicate the same logic.
I suspect the query you want to construct really looks like:
select 'a' as column_name, count(column_name), count(distinct column_name)
from t
union all
select 'a' as column_name, count(column_name), count(distinct column_name)
from t
union all
. . .
To construct this in SQL Server, you can use logic like this:
declare #q nvarchar(max);
set #q = '
select ''[column_name]'' as column_name, count([column_name]) as cnt, count(distinct [column_name]) as distinct_count
from [table_name]
';
declare #sql nvarchar(max);
select #sql = string_agg(replace(replace(#q,
'[column_name]',
quotename(column_name)
),
'[table_name]',
quotename(table_name)
), ' union all '
)
from information_schema.columns c
where table_name = #name; -- should probably check the schema too!
exec sp_executesql #sql;

query by partial column name

I have a
Checklist table and
there is 27 columns named "check1", "check2"..."check27".I would like to get all this values doing a query something like:
SELECT "check*" FROM Checklist;
Is this possible?
Which database? postgres, sqlite, mysql?
If select * is not an option, the most flexible approach is creating a dynamic query. You will first need to get the column names and then build your query:
DECLARE #tableName as varchar(100);
SET #tableName = 'Checklist';
DECLARE #columnList varchar(300);
SELECT #columnList = COALESCE(#columnList + ', ', '') + sc.name
FROM sysobjects so
INNER JOIN syscolumns sc ON so.id = sc.id
WHERE so.name = #tableName
AND sc.name LIKE 'check%'
DECLARE #query as varchar(4000);
SET #query = 'SELECT ' + #columnList + ' FROM ' + #tableName;
EXEC(#query);
The ending #query should contain SELECT check1, check2, check... FROM Checklist.
In Sql Server, this is terrible but you could do it... Building dynamic SQL
check% being your check* in the Select #columns query
DECLARE #columns NVARCHAR(max);
SELECT #columns = STUFF((
SELECT ',' + column_name
FROM INFORMATION_SCHEMA.columns
WHERE table_name = 'Checklist'
AND column_name LIKE 'check%'
FOR XML path('')
), 1, 1, '')
DECLARE #statement nvarchar(max) = 'SELECT ' + #columns + ' FROM Checklist'
EXECUTE sp_executesql #statement
Troll ass answer...
SELECT check1,check2,check3,check4,check5,check6,check7,check8,check9,check10,check11,check12,check13,check14,check15,check16,check17,check18,check19,check20,check21,check22,check23,check24,check25,check26,check27 FROM Checklist;

Dynamic query to find the length of rows in a column in sql server

I need to prepare a dynamic query to find the length of all the rows in a column in sql server. let say if there are 10 columns for a table with 100 rows. I need to find the row length for each column dynamically.
Assuming that your all columns are string columns, though len function should work anyways.
-- replace 'mytable' with the actual table name
declare #tableName nvarchar(128) = 'mytable';
declare #queryToRun nvarchar(max) = '';
-- IMPORTANT: following query is putting each column name as len_columnName
select #queryToRun = #queryToRun + ', len([' + c.name + ']) as [len_' + c.name + ']
'
from sys.tables as t
inner join sys.columns as c on t.object_id = c.object_id
where t.name = #tableName
-- removing the first comma
set #queryToRun = SUBSTRING(#queryToRun, 2, len(#queryToRun) - 1);
-- creating the query with dynamic column names
set #queryToRun = 'select ' + #queryToRun + ' from ' + #tableName;
--print #queryToRun
exec (#queryToRun)
you can use sys.tables and sys.all_columns
declare #Sql nvarchar(max)='select '
select #Sql=#sql+'Sum(len('+QUOTENAME(c.name)+')) as Len'+QUOTENAME(c.name)+',' from sys.tables t join sys.all_columns c on t.object_id=c.object_id
where t.Name='YourTableName'
set #Sql = left(#Sql,len(#sql)-1)+' from YourTableName'
select #Sql
Try this Script you will get data length of each columns in table dynamically
IF OBJECT_ID('dbo.LenghtOfRows')IS NOT NULL
DROP TABLE LenghtOfRows
CREATE TABLE LenghtOfRows (
Id Int IDENTITY,
Sqlode nvarchar(max)
)
DECLARE #SQL NVARCHAR(max),
#MinId INT,
#MaxId INT,
#tableName Varchar(100) ='StudentLabExamScore', --Give Table name here
#GetSQL NVARCHAR(max)
SET #SQL = 'SELECT ''SELECT DATALENGTH(''+COLUMN_NAME+'') As Len_'' +COLUMN_NAME +'' FROM ''+TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '''+#tableName+''''
PRINT #SQL
INSERT INTO LenghtOfRows(Sqlode)
EXEC ( #SQL)
SELECT #MinId = MIN(Id) from LenghtOfRows
SELECT #MaxId = MAX(Id) from LenghtOfRows
WHILE (#MInId <=#MaxId)
BEGIN
SELECT #GetSQL= Sqlode FROM LenghtOfRows WHERE id=#MInId
EXEC (#GetSQL)
PRINT #GetSQL
SET #MInId=#MInId+1
END

T-SQL: Select data from all tables reverted by INFORMATION_SCHEMA.TABLES

I need to extract data from all tables that were reverted by following query:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'ERP_%'
I've tried to execute following query, but without success:
SELECT *
FROM
(SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'ERP_%')
WHERE STATUS = 'XXX'
Looking forward to your assistance.
You may try to generate a dynamic SQL statement and execute it:
-- Declarations
DECLARE #stm nvarchar(max)
SET #stm = N''
-- Dynamic SQL
SELECT #stm = (
SELECT CONCAT(
N'SELECT * FROM ',
QUOTENAME(TABLE_NAME),
N' WHERE [STATUS] = ''XXX''; '
)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'ERP_%'
FOR XML PATH('')
)
-- Execution
PRINT #stm
EXEC sp_executesql #stm
Try this query using dynamic SQL:
declare #sql varchar(max) = '';
select #sql = #sql + 'select * from ' + TABLE_NAME + ' where [status] = ''XXX''; '
from INFORMATION_SCHEMA.TABLES
where TABLE_NAME like 'ERP_%';
exec(#sql);