SQL——获取所有表计数的快速方法

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

如果数据库 d1 有表 T1,T2,T3,T4,所有表的字段都是 "Date1"

计算所有表中日期早于 3 天前的所有记录的最佳方法是什么?

我知道可以做联合,我假设没有漂亮的语法可以省略所有表[就像 C++ 中的 'parent' 对象]。

这里的best可能意味着更高效,或者只是T-SQL中令人愉悦的语法。

这是针对 SSMS 17.7 的。微软 SQL 服务器 2014 (SP2)

如果您事先知道 table 个名称,对 union all 进行简单查询可能是最简单的方法:

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())

如果您事先不知道 table 名称,您可以使用 information_schema.columns 动态构建联合查询。

没有联合?

既然 COUNT 没有 GROUP BY returns 1 值,为什么不使用 CROSS JOIN 一次呢?

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

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

Sql 服务器的示例片段:

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

那么,您对父对象感兴趣,那就是视图。您可以将其重复用于各种查询。或者,如果需要,可以添加更多列:

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;

现在,可以按照你想要的方式查询

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

您可以使用 CTE(通用 Table 表达式)代替创建视图。它像视图一样工作,但不会持久存在于数据库中。请试一试:

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())        

它适用于所有 SQL 大于或等于 2005 的服务器。