TSQL - быстрый способ подсчета всех таблиц

Если база данных d1 есть столы T1,T2,T3,T4 все с поля "Date1",

Каков наилучший способ подсчета всех записей во всех таблицах с датой старше 3 дней назад?

Я знаю, что можно создавать объединения, я предполагаю, что нет изящного синтаксиса, который бы пропускал все таблицы [как "родительский" объект в C++].

Здесь лучшее может означать более эффективный или просто приятный синтаксис в T-SQL.

Это для SSMS 17.7. Microsoft SQL Server 2014 (SP2)

3 ответа

Решение

Ну, вы заинтересованы в родительском объекте, тогда это будет представление. Вы можете использовать его для различных запросов. Или добавьте больше столбцов, если они вам нужны:

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

Если вы заранее знаете имена таблиц, простой запрос на объединение всех, вероятно, будет самым простым способом:

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

Если вы не знаете названия таблиц заранее, вы можете использовать information_schema.columns построить объединенный запрос динамически.

Без СОЮЗА?

Так как COUNT без GROUP BY возвращает 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 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

Возвращает:

T1  T2  T3  T4  T1234
3   2   1   0   6

Вместо создания представления вы можете использовать CTE (Common Table Expression). Он работает как представление, но не сохраняется в базе данных. Пожалуйста, попробуйте:

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 Server старше или равных 2005.

Другие вопросы по тегам