如何在多个表中获取日期列的最大日期值

时间:2018-07-30 16:09:52

标签: sql sql-server

例如,我在数据库中有2个表。 例如: 表T:

declare @t table (name varchar(20),DOB date)
Insert into @t (name,DOB) values ('Mohan','2001-07-19')
Insert into @t (name,DOB) values ('Minu','1998-06-19')

表:TT

declare @tt table (name varchar(20),DOB date)
Insert into @tt (name,DOB) values ('Raju','2010-07-19')
Insert into @tt (name,DOB) values ('Rani','2001-06-19')

现在我有一个查询,可以基于日期类型过滤器获取多个表的表名和列名。

SELECT   C.TABLE_SCHEMA, c.TABLE_NAME,c.COLUMN_NAME
FROM     INFORMATION_SCHEMA.COLUMNS c 
         JOIN sys.objects o ON o.name = c.TABLE_NAME   
WHERE    o.type = 'U' AND C.DATA_TYPE = 'Datetime'

输出:

T_Schema    T_name T_column
  dbo         T      DOB   
  dbo         TT     DOB

但是如何获得两个表的最大日期,如下所示:

  T_Schema  T_name T_column  Max_dt
  dbo         T      DOB     2001-07-19
  dbo         TT     DOB     2010-07-19

建议我实现这一目标的最佳方法。

4 个答案:

答案 0 :(得分:6)

这是不使用光标的另一个选项。我怀疑从性能的角度来看会不会更好,因为您仍然需要为每一行使用子查询。但是我真的很讨厌游标。我还使用了系统表而不是信息模式视图,因为有时它们可​​能有些奇怪。 https://sqlblog.org/2011/11/03/the-case-against-information_schema-views

declare @SQL nvarchar(max) = N''

select @SQL = @SQL + 
    N'select SCHEMA_NAME = ''' + QUOTENAME(s.name) + ''', TABLE_NAME = ''' 
        + QUOTENAME(o.name) + ''', COLUMN_NAME = '''
        + QUOTENAME(c.name) + ''', MaxDate = '
        + '(select MAX(' + QUOTENAME(c.name) + ') from  ' + QUOTENAME(s.name) + '.' + QUOTENAME(o.name) + ') UNION ALL '
from sys.columns c
join sys.systypes st on st.type = c.system_type_id
join sys.objects o on o.object_id = c.object_id and o.type = 'U'
join sys.schemas s on s.schema_id = o.schema_id
where st.name = 'datetime'
order by s.name
    , o.name
    , c.name

set @SQL = left(@SQL, len(@SQL) - 10) --removes final UNION ALL

select @SQL

--uncomment below when you are satisfied the dynamic sql is correct
--exec sp_executesql @SQL

答案 1 :(得分:3)

这里有一些动态SQL,可以通过游标执行所需的操作。

如果您有很多表,请谨慎使用,或者先在测试中运行它。一般而言,游标的表现不佳。您可以针对系统数据库(例如master)运行此数据库,该数据库具有较少的值以查看其工作方式。

create table #MaxDate (tname varchar(256), cname varchar(256), mdate datetime)

declare cur cursor local fast_forward
for 
    SELECT   C.TABLE_SCHEMA, c.TABLE_NAME,c.COLUMN_NAME
    FROM     INFORMATION_SCHEMA.COLUMNS c 
             JOIN sys.objects o ON o.name = c.TABLE_NAME   
    WHERE    o.type = 'U' AND C.DATA_TYPE = 'Datetime'

declare @schema varchar(64), @table varchar(256), @column varchar(256)
declare @sql varchar(max)

open cur
fetch next from cur into @schema, @table, @column 
while @@FETCH_STATUS = 0

begin
    set @sql = 'select ''' + @table + '''' + ',''' + '' + @column + '''' + ',' +  'max(' + @column + ') from ' + @schema + '.' + @table
    print @sql

    insert into #MaxDate
    exec (@sql)
    fetch next from cur into @schema, @table, @column
end

close cur
deallocate cur

select * from #MaxDate
drop table #MaxDate

答案 2 :(得分:3)

以下是使用游标,动态SQL和临时表的答案:

openssl genrsa -out cluster-admin-key.pem 4096
openssl req -new -key cluster-admin-key.pem -out cluster-admin.csr -subj "/CN=cluster-admin/O=system:masters"
openssl x509 -req -in cluster-admin.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cluster-admin.pem -days 3650

答案 3 :(得分:2)

SQL为您构建SQL

DECLARE @SQL as nvarchar(max) ='';
select @SQL = @SQL + 'SELECT ' + Column_Name + ' adate, ''' + Column_Name + ''' colname, ''' + Table_name + ''' tabname  FROM ' +  Table_name + ' UNION ' FROM   INFORMATION_SCHEMA.COLUMNS where data_type like '%date%'
select @SQL = 'SELECT TOP 100 * FROM (' + LEFT(@SQL, LEN(@SQL) -6) + ') IQ  WHERE IQ.adate IS NOT null ORDER BY IQ.adate DESC';

 --cut n paste the sql below, see what it does for you
select @SQL

mark II-为您执行sql,并在其中排序带有空格的名称

DECLARE @SQL as nvarchar(max) ='';
select @SQL = @SQL + 'SELECT [' + Column_Name + '] adate, ''' + Column_Name + ''' colname, ''' + Table_name + ''' tabname  FROM [' +  Table_name + '] UNION ' FROM   INFORMATION_SCHEMA.COLUMNS where data_type like '%date%'
select @SQL = 'SELECT TOP 100 * FROM (' + LEFT(@SQL, LEN(@SQL) -6) + ') IQ  WHERE IQ.adate IS NOT null ORDER BY IQ.adate DESC';

select @SQL;
EXEC sp_executesql @sql;