Resultset from Facts across different schemas - sql

We have a DB which has several schemas and each schema has a Fact table. I need to prepare a result set with schema name, max(MTH_DT) from Fact and distinct MTH_DT counts from each Fact table.
SCHEMA_NAME MAX(MTH_DT) DISTINCT_COUNT(MTH_DT)
SCHM_1 11/30/2015 24
SCHM_2 10/31/2015 24
SCHM_3 11/30/2015 36
SCHM_4 10/31/2015 24
SCHM_5 11/30/2015 24
How can I get the resultset in this fashion?

Here it goes
Just uncomment the EXECUTE statement when you are sure of the query and run the query:
DECLARE #SQL VARCHAR(MAX) = ''
SELECT #SQL += 'SELECT '''+T.TABLE_NAME+''' AS [SCHEMA_NAME],MAX(MTH_DT) AS [MAX(MTH_DT)] ,COUNT(MTH_DT) AS [DISTINCT_COUNT(MTH_DT)] FROM '+T.TABLE_SCHEMA+'.'+T.TABLE_NAME + ' UNION ' FROM INFORMATION_SCHEMA.TABLES AS T WHERE T.TABLE_NAME like 'SCHM_%'
SELECT #SQL = SUBSTRING(#SQL,1,LEN(#SQL) - LEN('UNION'))
PRINT (#SQL)
--EXECUTE (#SQL)

Here is a safer way to build your dynamic sql than using INFORMATION_SCHEMA.TABLES. I left off the group by because it is a constant so you don't actually need a group by.
declare #SQL nvarchar(MAX) = ''
select #SQL = #SQL + 'select ''' + name + ''' as SchemaName, MAX(MTH_DT) as MaxMTH_DT, COUNT(distinct MTH_DT) as DISTINCT_COUNT_MTH_DT from ' + name + '.Fact union all '
from sys.schemas
where SCHEMA_ID > 4
and SCHEMA_ID < 16384
Select #SQL = LEFT(#SQL, LEN(#SQL) - 9) + ' order by SchemaName'
select #SQL

Related

Dynamic SQL can make it?

I have one table named AskLists with 2 fields :
AskListId AskInterview
2032 5
2032 3
2032 4
2032 6
5076 1
5076 3
5076 4
5076 5
5076 6
For each distinct number of the field AskListId, there is a table named by the number AskList'Number'
For example AskList5076 :
AskInterview QUOTA7
1 5660424
2 5660424
3 5660424
4 5667511
5 5667511
6 5667511
7 5667511
So there are hundred of tables AskList'Number'.
I am trying to add the field QUOTA7 which we can find in every AskList'Number' table to the main table AskLists.
For one table, it's easy :
SELECT AskListId
, AskInterview
,AskList5076.QUOTA7
FROM [Lists].[dbo].[AskLists]
INNER JOIN AskList5076 on AskLists.AskInterview = AskList5076.AskInterview
But I need to make it for all the values inside AskListId...
Is it possible to make it without making manually hundred of requests ?
I was told Dynamic SQL could make it but I don't know about it.
Have a look at the following and see if this works for you. It might require some slight tweaking and of course modifying to be an update, but in the context of your desired query shown above this should give you the values from each table.
declare #sql nvarchar(max)=''
select #sql +='
select al.AsklistId, al.AskInterview, aq.quota7
from lists.dbo.AskLists al join '
+ QuoteName(table_name)
+ ' on al.AskInterview=aq.AskInterview'
+ Iif(Count(*) over()=Row_Number() over(order by (select null)),'',' union all')
from INFORMATION_SCHEMA.COLUMNS
where table_name like 'Asklist%'
and table_name != 'Asklist'
and column_name='QUOTA7'
print #sql
-- exec sp_executesql #sql
You could use Dynamic SQL to union all your tables together before you join them.
Essentially putting them into the style of structure they should have been in in the first place
Something like this (it's more than a bit hacky)...
DECLARE #union NVARCHAR(MAX)
SELECT
#union =
STRING_AGG(
CAST(N'SELECT ''' + TABLE_NAME + N''' AS source_table, * FROM ' + TABLE_CATALOG + N'.' + TABLE_SCHEMA + N'.' + TABLE_NAME AS NVARCHAR(MAX)),
CHAR(13)+CHAR(10) + N'UNION ALL' + CHAR(13)+CHAR(10)
)
FROM
INFORMATION_SCHEMA.TABLES
WHERE
TABLE_NAME LIKE 'AskList%'
AND TABLE_NAME <> 'AskLists'
AND TABLE_CATALOG = 'Lists'
AND TABLE_SCHEMA = 'dbo'
;
DECLARE #sql NVARCHAR(MAX) = N'
WITH
unioned
AS
(
' + #union + '
)
SELECT
AskLists.AskListId
, AskLists.AskInterview
, unioned.QUOTA7
FROM
AskLists
INNER JOIN
unioned
on unioned.source_table = ''AskList'' + CAST(AskLists.AskListID AS VARCHAR(MAX))
and unioned.AskInterview = AskLists.AskInterview
'
EXEC sp_executesql #sql
Demo: db<>fiddle

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;

No of records in each table [duplicate]

This question already has answers here:
Query to list number of records in each table in a database
(23 answers)
Closed 5 years ago.
How to get a list of all tables with no of records in a particular database in SQL Server.
Thanks
Here's another option - not dependent on INFORMATION_SCHEMA.
This would also allow you to alter your where clause (you may edit your #QUERY accordingly).
DECLARE #QUERY VARCHAR(MAX)
SET #QUERY = ''
/*
* Create a long query with a row count + table name.
* You may alter your where clause here
*/
SELECT #QUERY =
#QUERY + ' SELECT COUNT(*), ''' + QUOTENAME(name)
+ ''' FROM ' + QUOTENAME(name) + CHAR(13)
+ 'UNION ALL'
FROM sys.tables
--Get rid of the last 'UNION ALL'...
SELECT #QUERY = LEFT(#QUERY, LEN(#QUERY) - 10)
--Prepare a temp table - drop if exists and then create it
IF object_id('tempdb..#TableResults') IS NOT NULL
DROP TABLE #TableResults
CREATE TABLE #TableResults(
Count INT,
TableName VARCHAR(MAX)
);
--Insert the main query result into the temp table
INSERT INTO #TableResults
EXEC(#QUERY);
--Select all from the temp table
SELECT * FROM #TableResults
WHERE COUNT = 0
You will need to use Dynamic SQL and check for existance of rows in each table
declare #sql nvarchar(max)
select #sql = isnull(#sql + ' union all ' + char(13) , convert(nvarchar(max), ''))
+ 'select tbl_name = ''' + name + ''' '
+ 'where not exists (select * from ' + quotename(name) + ')'
from sys.tables
print #sql
exec (#sql)
Did you mean this
SELECT COUNT(*) FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN
(
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE')
Saravanan

Query Across different database - Same table SQL Server 2012

I Have a common table "User Activity" in about 200 different databases on different servers, is it possible to select rows from all databases for that table in one statement?
I have a list of those databases and servers they are on ina main database/table, can obtain by
Select servername, dbname from DBases from CustomersList
Yes but you need to explicitly mention them all:
SELECT COl1,Col2,Col3 FROM Database1.schema.Table1
UNION ALL
SELECT COl1,Col2,Col3 FROM Database2.schema.Table1
UNION ALL
SELECT COl1,Col2,Col3 FROM Database3.schema.Table1
UNION ALL
.......
...
SELECT COl1,Col2,Col3 FROM Database200.schema.Table1
This is the kind of thing I would just build in Excel and paste into SSMS.
Then you might want to reconsider whether it's a good design to have this in 200 databases.
I am getting this error:
Incorrect syntax near 'ALL'
While I try to run your code.
I have address table in two databases so I modified your code as:
DECLARE #tableName nvarchar(256) = 'dbo.Address'
DECLARE #sql nvarchar(max) = ''
SELECT #sql = #sql + 'SELECT * FROM [' + dbs.name + ']..[' + #tableName + '] '
+ CASE WHEN #sql <> '' THEN 'UNION ALL ' ELSE '' END
FROM sys.sysdatabases dbs where dbs.dbid in (7,8)
and dbs.name NOT IN ('master', 'tempdb', 'msdb', 'model','SSISall')
EXEC(#sql)
I suggest you to use this syntax:
DECLARE #tableName nvarchar(256) = 'Table1'
DECLARE #sql nvarchar(max) = ''
SELECT #sql = #sql + CASE WHEN #sql <> '' THEN 'UNION ALL ' ELSE '' END
+ 'SELECT * FROM [' + dbs.name + ']..[' + #tableName + '] '
FROM sys.sysdatabases dbs
WHERE dbs.name NOT IN ('master', 'tempdb', 'msdb', 'model')
EXEC(#sql)
You can easily optimize it to use in a stored procedure.

How to get count across multiple tables

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