我需要创建一个物化 View 来循环 pg_tables
中的所有工作列表。
首先我创建一个查询,然后尝试创建一个 for 循环。
这是我的第一个代码没有 for 循环。
SELECT
count(visit_num) AS total_claim_count,
count(user_id) as assigned_count,
(count(visit_num)-count(user_id)) AS not_assigned_count,
count(case when doe <= (SELECT doe - INTERVAL '30 days') and user_id is not null then 1 end ) AS Assigned_Last_30_Days,
(count(user_id)-count(case when doe <= (SELECT doe - INTERVAL '30 days') and user_id is not null then 1 end )) AS not_Assigned_last_30_days,
count(case when doe >= (SELECT doe - INTERVAL '30 days') and user_id is not null then 1 end ) AS Assigned_before_30_Days,
count(case when doe > (SELECT doe - INTERVAL '30 days') and user_id is null then 1 end ) AS not_Assigned_before_30_days,
count(CASE WHEN date_worked is not null then 1 end) followed_up,
count(CASE WHEN last_denied_date is not null then 1 end) denials,
count(case when status_and_action_code='No Status - Need to follow-up' then 1 end) AS no_status
FROM Worklist_123456
这是我尝试过的代码带有for循环。但它不起作用。
DO $$
DECLARE
pg_tables varchar(1000000);
tbl_name record;
tablename varchar(1000000);
begin
For tbl_name IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND tablename LIKE 'worklist¥_%' ESCAPE '¥'
loop
tablename := tbl_name.tablename;
SELECT
count(visit_num) AS total_claim_count,
count(user_id) as assigned_count,
(count(visit_num)-count(user_id)) AS not_assigned_count,
count(case when doe <= (SELECT doe - INTERVAL '30 days') and user_id is not null then 1 end ) AS Assigned_Last_30_Days,
(count(user_id)-count(case when doe <= (SELECT doe - INTERVAL '30 days') and user_id is not null then 1 end )) AS not_Assigned_last_30_days,
count(case when doe >= (SELECT doe - INTERVAL '30 days') and user_id is not null then 1 end ) AS Assigned_before_30_Days,
count(case when doe > (SELECT doe - INTERVAL '30 days') and user_id is null then 1 end ) AS not_Assigned_before_30_days,
count(CASE WHEN date_worked is not null then 1 end) followed_up,
count(CASE WHEN last_denied_date is not null then 1 end) denials,
count(case when status_and_action_code='No Status - Need to follow-up' then 1 end) AS no_status
FROM tablename;
END LOOP;
END; $$;
它给出这样的错误。
ERROR: column reference "tablename" is ambiguous
LINE 1: SELECT tablename FROM pg_tables WHERE schemaname = 'public' ...
^
DETAIL: It could refer to either a PL/pgSQL variable or a table column.
QUERY: SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND tablename LIKE 'worklist¥_%' ESCAPE '¥'
CONTEXT: PL/pgSQL function inline_code_block line 9 at FOR over SELECT rows
SQL state: 42702
任何人都可以帮我解决这个问题。谢谢。
最佳答案
如pointed out通过 @Frank Heikens ,您正在考虑 dynamic SQL条款: demo
DO $proc$
DECLARE tbl_name record;
BEGIN
FOR tbl_name IN SELECT tablename
FROM pg_tables
WHERE schemaname = 'public'
AND tablename LIKE 'worklist¥_%' ESCAPE '¥'
LOOP execute format($dynamic_sql_query$
INSERT INTO anon_proc_output
SELECT
%1$L AS source_table --first argument (1$), as a string Literal (L)
, count(visit_num) AS total_claim_count
, count(user_id) AS assigned_count
,(count(visit_num)
-count(user_id) ) AS not_assigned_count
, count(user_id)filter(where doe <= (SELECT doe - INTERVAL '30 days') ) AS Assigned_Last_30_Days
,(count(user_id)
-count(user_id)filter(where doe <= (SELECT doe - INTERVAL '30 days') ) ) AS not_Assigned_last_30_days
, count(user_id)filter(where doe >= (SELECT doe - INTERVAL '30 days') ) AS Assigned_before_30_Days
, count(*)filter(where doe > (SELECT doe - INTERVAL '30 days')
and user_id is null) AS not_Assigned_before_30_days
, count(date_worked) AS followed_up
, count(last_denied_date) AS denials
, count(*)filter(where status_and_action_code='No Status - Need to follow-up') AS no_status
FROM %1$s; --still the same first argument, hence the 1$, but this time as-is, hence the s
$dynamic_sql_query$
, tbl_name.tablename);--this is used to replace %1$L %1$s
END LOOP;
END $proc$;
count(case...)
正在模拟聚合FILTER
条款。doe>=(SELECT doe-INTERVAL '30 days')
毫无意义。您正在检查该值是否大于其自身,是否减少。这实际上是some_number>=(some_number-1)
。-
count(arg)
doesn't count rows wherearg
is null :
count ( "any" ) → bigint
Computes the number of input rows in which the input value is not null.
so
count(case when arg is not null then 1 end)
与count(arg)
相同,count(case when (condition) and arg is not null then 1 end)
与count(arg)filter(where (condition)) 相同
.您可能需要重新思考在何处以及为何使用
count(arg)
,而不是count(*)
和count(case when arg is不为空则 1 结束)
。
关于sql - postgreSQL 中的循环表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75763956/