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.