【问题标题】:PostgreSQL dynamic query: find most recent timestamp of several unrelated tablesPostgreSQL动态查询:查找几个不相关表的最新时间戳
【发布时间】:2022-01-03 01:30:03
【问题描述】:

我有很多表,其中许多都有timestamp 列。我可以得到一个包含时间戳列的每个表的列表:

SELECT table_name 
FROM information_schema.columns 
WHERE table_schema='my_schema' AND column_name='timestamp';

--------------
 table_name               
--------------
 apples
 bananas
 sharks
 lemons

我可以得到鲨鱼表中最高的时间戳如下

SELECT MAX(timestamp) FROM sharks;

-------------------------
           max           
-------------------------
 2021-11-24 00:00:00.000

我想要一张这样的桌子

 table_name  |       last_updated               
-------------+-------------------------
 apples      | 2021-11-23 00:02:00.000
 bananas     | 2019-10-16 00:04:00.000
 sharks      | 2021-11-24 00:00:00.000
 lemons      | 1970-01-03 10:00:00.000

我怀疑这需要动态 SQL,所以我正在尝试类似

SELECT (
    EXECUTE 'SELECT MAX(timestamp) FROM my_schema.' || table_name
) FROM (
    SELECT table_name 
    FROM information_schema.columns 
    WHERE table_schema='my_schema' AND column_name='timestamp'
);

但似乎 EXECUTE 在子查询中不起作用。

性能不是特别关注的问题,只是产生预期的结果。

【问题讨论】:

标签: sql postgresql dynamic-sql information-schema


【解决方案1】:

动态查询无法在 PL/pgSQL 块之外运行,因此您需要将代码封装在一个中。

我设置了与您类似的测试表,它们之间仅共享“时间戳”列:

drop table if exists public.sharks_70099803 cascade; 
create table public.sharks_70099803 
as  select  1::int integer_column, 
            now()::timestamp as "timestamp";
drop table if exists public.bananas_70099803 cascade; 
create table public.bananas_70099803
as select   'some text'::text text_column, 
            now()::timestamp as "timestamp";

在 PL/pgSQL 函数中包装一个动态查询。在内部,我构建了一个查询以从每个带有列的表中提取max(timestamp),然后将它们聚合到一个查询中,中间有一个union all,我稍后会执行。

CREATE OR REPLACE FUNCTION public.test_70099803()
RETURNS SETOF RECORD
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN 
    return query 
    execute (
        select string_agg(select_per_table,' union all ') 
        from (  
            select 'select '''||
                    table_name||
                    ''' as table_name, max(timestamp) from public.'||
                    table_name "select_per_table" 
            from information_schema.columns 
            where table_schema='public' 
            and column_name='timestamp'
        ) a
    );
END 
$BODY$;

select * from public.test_70099803() as t(table_name text, max_timestamp timestamp);
--    table_name    |       max_timestamp
--------------------+----------------------------
-- sharks_70099803  | 2021-11-24 17:12:03.24951
-- bananas_70099803 | 2021-11-24 17:12:03.253614
--(2 rows)

您可以对函数进行参数化以适用于更多表组,或者具有预定义的输出表结构,让您只需 select * from test_70099803();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-02
    • 2014-03-02
    • 2015-04-01
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多