JosephDoggie
JosephDoggie

Reputation: 1594

TSQL -- quick way to get a count across all tables

If database d1 has tables T1,T2,T3,T4 all with the field "Date1".

What is the best way to get a count of all records across all tables with a date older than 3 days ago?

I know one could do unions, I assume there is no nifty syntax that would omit all tables [like a 'parent' object in C++].

Here best may mean more efficient, or just a pleasing syntax in T-SQL.

This is for SSMS 17.7. Microsoft SQL Server 2014 (SP2)

Upvotes: 0

Views: 58

Answers (4)

user153383
user153383

Reputation: 11

Instead create a view, you can use a CTE (Common Table Expression). It works like a view, but not persists on database. Please try it:

WITH CteDate( Date1 )
AS ( SELECT Date1 FROM t1 UNION ALL
     SELECT Date1 FROM t2 UNION ALL
     SELECT Date1 FROM t3 UNION ALL
     SELECT Date1 FROM t4
    )
SELECT COUNT(*) FROM CteDate WHERE Date1 <= DATEADD(DAY, -3, GETDATE())        

It works for all SQL Server greater or equal then 2005.

Upvotes: 1

LukStorms
LukStorms

Reputation: 29667

Without UNION?

Since a COUNT without a GROUP BY returns 1 value, why not use CROSS JOIN for once?

SELECT 
 t1.Cnt AS [T1], 
 t2.Cnt AS [T2], 
 t3.Cnt AS [T3],
 t4.Cnt AS [T4],
 (t1.Cnt + t2.Cnt + t3.Cnt + t4.Cnt) AS [T1234]
FROM 
(SELECT COUNT(*) AS Cnt FROM T1 WHERE [Date1] < CAST(GetDate()-3 AS DATE)) AS t1
CROSS JOIN
(SELECT COUNT(*) AS Cnt FROM T2 WHERE [Date1] < CAST(GetDate()-3 AS DATE)) AS t2
CROSS JOIN
(SELECT COUNT(*) AS Cnt FROM T3 WHERE [Date1] < CAST(GetDate()-3 AS DATE)) AS t3
CROSS JOIN
(SELECT COUNT(*) AS Cnt FROM T4 WHERE [Date1] < CAST(GetDate()-3 AS DATE)) AS t4

Or a CROSS APPLY

SELECT 
 t1.Cnt AS [T1], 
 t2.Cnt AS [T2], 
 t3.Cnt AS [T3],
 t4.Cnt AS [T4],
 (t1.Cnt + t2.Cnt + t3.Cnt + t4.Cnt) AS [T1234]
FROM (SELECT CAST(GetDate()-3 AS DATE) as Dt) d
CROSS APPLY (SELECT COUNT(*) AS Cnt FROM T1 WHERE [Date1] < d.Dt) AS t1
CROSS APPLY (SELECT COUNT(*) AS Cnt FROM T2 WHERE [Date1] < d.Dt) AS t2
CROSS APPLY (SELECT COUNT(*) AS Cnt FROM T3 WHERE [Date1] < d.Dt) AS t3
CROSS APPLY (SELECT COUNT(*) AS Cnt FROM T4 WHERE [Date1] < d.Dt) AS t4

Example snippet for Sql Server:

declare @T1 table (id int primary key identity(1,1), [Date1] date);
declare @T2 table (id int primary key identity(1,1), [Date1] date);
declare @T3 table (id int primary key identity(1,1), [Date1] date);
declare @T4 table (id int primary key identity(1,1), [Date1] date);

insert into @T1 ([Date1]) values (getdate()-6),(getdate()-5),(getdate()-4),(getdate()-3),(getdate()-2),(getdate()-1),(getdate()-0);
insert into @T2 ([Date1]) select top 6 [Date1] from @T1 order by [Date1] desc;
insert into @T3 ([Date1]) select top 5 [Date1] from @T1 order by [Date1] desc;
insert into @T4 ([Date1]) select top 4 [Date1] from @T1 order by [Date1] desc;

SELECT 
 t1.Cnt AS [T1], 
 t2.Cnt AS [T2], 
 t3.Cnt AS [T3],
 t4.Cnt AS [T4],
 (t1.Cnt + t2.Cnt + t3.Cnt + t4.Cnt) AS [T1234]
FROM 
(SELECT COUNT(*) AS Cnt FROM @T1 WHERE [Date1] < CAST(GetDate()-3 AS DATE)) AS t1
CROSS JOIN
(SELECT COUNT(*) AS Cnt FROM @T2 WHERE [Date1] < CAST(GetDate()-3 AS DATE)) AS t2
CROSS JOIN
(SELECT COUNT(*) AS Cnt FROM @T3 WHERE [Date1] < CAST(GetDate()-3 AS DATE)) AS t3
CROSS JOIN
(SELECT COUNT(*) AS Cnt FROM @T4 WHERE [Date1] < CAST(GetDate()-3 AS DATE)) AS t4

Returns:

T1  T2  T3  T4  T1234
3   2   1   0   6

Upvotes: 1

Lukas Eder
Lukas Eder

Reputation: 220952

Well, you're interested in a parent object, that would be a view, then. You can reuse it for a variety of queries. Alternatively, add more columns if you need them:

CREATE VIEW parent AS
SELECT Date1 FROM t1 UNION ALL
SELECT Date1 FROM t2 UNION ALL
SELECT Date1 FROM t3 UNION ALL
SELECT Date1 FROM t4;

And now, that can be queried in the way you want

SELECT COUNT(*) FROM parent WHERE Date1 <= DATEADD(DAY, -3, GETDATE())

Upvotes: 1

Zohar Peled
Zohar Peled

Reputation: 82474

If you know the table names in advance, a simple query on union all will probably be the simplest way:

SELECT COUNT(*)
FROM
(
     SELECT Date1
     FROM T1
     UNION ALL
     SELECT Date1
     FROM T2
     SELECT Date1
     FROM T3
     SELECT Date1
     FROM T4
) As t
WHERE Date1 <= DATEADD(DAY, -3, GETDATE())

If you don't know the table names in advance, you can use information_schema.columns to build the union query dynamically.

Upvotes: 2

Related Questions