如何用pl/pgSQL来处理'comma separated list'returns?
How to use pl/pgSQL to handle 'comma separated list' returns?
我正在尝试 UNION ALL
将许多 table 放入新的 table.The 列中,旧 table 的列是相同的,但列的顺序是不同,所以下面的 SQL 语句会得到错误的结果:
CREATE TABLE sum_7_2018_xia_weijian
AS
(
SELECT * FROM huiwen
UNION
SELECT * FROM penglai
UNION
SELECT * FROM baoluo
UNION
SELECT * FROM dongge
UNION
SELECT * FROM resultdonglu
UNION
SELECT * FROM resultwencheng
UNION
SELECT * FROM tan_illeg
);
我终于更正了,但是SQL语句太多余了:
第 1 步。获取名为 huiwen
的旧 table 之一的列名称
SELECT string_agg(column_name, ',')
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'huiwen';
结果:
> string_agg
> ----------------------------------------------------------------------
>
> gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
第 2 步。将 table 合并为一个新的 table。我将 table huiwen
的 string_agg
复制到每个 SELECT-UNION 以保持列的顺序,这很笨拙。
CREATE TABLE sum_2018_xia_weijian
AS
(
SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
FROM huiwen
UNION ALL
SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
FROM penglai
UNION ALL
SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
FROM baoluo
);
结果:
> Query returned successfully: 2206 rows affected, 133 msec execution time.
我尝试通过 pl/pgSQL
使用 Declarations
变量来处理列名来进行一些优化,但未能找到任何 SQL 数据类型可以处理此问题。使用RECORD
结果Pseudo-Types ERROR
:
CREATE or replace FUNCTION ct() RETURNS RECORD AS $$
DECLARE
clms RECORD;
BEGIN
SELECT column_name INTO clms
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'huiwen';
RETURN clms;
END;
$$ LANGUAGE plpgsql;
CREATE TABLE sum_2018_xia_weijian
AS
(
SELECT ct() FROM huiwen
UNION ALL
SELECT ct() FROM penglai
UNION ALL
SELECT ct() FROM baoluo
UNION ALL
SELECT ct() FROM dongge
UNION ALL
SELECT ct() FROM resultdonglu
UNION ALL
SELECT ct() FROM resultwencheng
UNION ALL
SELECT ct() FROM tan_illeg
);
您可以遵循 Union 或 Union All 文档中的以下一些概念,而不是使编程块变得复杂:
- 所有查询中的列数必须相同。
- 相应的列必须具有兼容的数据类型。
- 第一个查询的列名决定合并结果集的列名。
- GROUP BY 和 HAVING 子句应用于每个单独的查询,而不是最终结果集。
- ORDER BY 子句应用于组合结果集,而不是单个结果集中。
按照第 3 点,将您的联合查询调整为引用 table,其列顺序在结果中是预期的。
您可以使用 STRING_AGG
两次以获得 UNION ALL
。您可以通过 string_agg
.
中的 column_name
显式排序来按特定顺序获取所有列
这是一个通用函数,它采用 table 数组和最终的 table 名称。
CREATE or replace FUNCTION fn_create_tab(tname_arr TEXT[], p_tab_name TEXT)
RETURNS VOID AS $$
DECLARE
l_select TEXT;
BEGIN
select STRING_AGG(query,' UNION ALL ' ) INTO l_select
FROM
(
SELECT 'select ' || string_agg( column_name,','
ORDER BY column_name ) || ' from ' || table_name as query
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = ANY (tname_arr)
GROUP BY table_name
) s;
IF l_select IS NOT NULL
THEN
EXECUTE format ('DROP TABLE IF EXISTS %I',p_tab_name);
EXECUTE format ('create table %I AS %s',p_tab_name,l_select);
END IF;
END;
$$ LANGUAGE plpgsql;
现在,运行函数如下:
select fn_create_tab(ARRAY['huiwen','penglai'],'sum_2018_xia_weijian');
我正在尝试 UNION ALL
将许多 table 放入新的 table.The 列中,旧 table 的列是相同的,但列的顺序是不同,所以下面的 SQL 语句会得到错误的结果:
CREATE TABLE sum_7_2018_xia_weijian
AS
(
SELECT * FROM huiwen
UNION
SELECT * FROM penglai
UNION
SELECT * FROM baoluo
UNION
SELECT * FROM dongge
UNION
SELECT * FROM resultdonglu
UNION
SELECT * FROM resultwencheng
UNION
SELECT * FROM tan_illeg
);
我终于更正了,但是SQL语句太多余了:
第 1 步。获取名为 huiwen
SELECT string_agg(column_name, ',')
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'huiwen';
结果:
> string_agg
> ----------------------------------------------------------------------
>
> gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
第 2 步。将 table 合并为一个新的 table。我将 table huiwen
的 string_agg
复制到每个 SELECT-UNION 以保持列的顺序,这很笨拙。
CREATE TABLE sum_2018_xia_weijian
AS
(
SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
FROM huiwen
UNION ALL
SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
FROM penglai
UNION ALL
SELECT gid,id,geom,sxm,sxdm,sxxzqdm,xzqhdm,xzmc,sfzgjsyd,sfkfbj,sfjbnt,sfld,sflyhx,sfhyhx
FROM baoluo
);
结果:
> Query returned successfully: 2206 rows affected, 133 msec execution time.
我尝试通过 pl/pgSQL
使用 Declarations
变量来处理列名来进行一些优化,但未能找到任何 SQL 数据类型可以处理此问题。使用RECORD
结果Pseudo-Types ERROR
:
CREATE or replace FUNCTION ct() RETURNS RECORD AS $$
DECLARE
clms RECORD;
BEGIN
SELECT column_name INTO clms
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'huiwen';
RETURN clms;
END;
$$ LANGUAGE plpgsql;
CREATE TABLE sum_2018_xia_weijian
AS
(
SELECT ct() FROM huiwen
UNION ALL
SELECT ct() FROM penglai
UNION ALL
SELECT ct() FROM baoluo
UNION ALL
SELECT ct() FROM dongge
UNION ALL
SELECT ct() FROM resultdonglu
UNION ALL
SELECT ct() FROM resultwencheng
UNION ALL
SELECT ct() FROM tan_illeg
);
您可以遵循 Union 或 Union All 文档中的以下一些概念,而不是使编程块变得复杂:
- 所有查询中的列数必须相同。
- 相应的列必须具有兼容的数据类型。
- 第一个查询的列名决定合并结果集的列名。
- GROUP BY 和 HAVING 子句应用于每个单独的查询,而不是最终结果集。
- ORDER BY 子句应用于组合结果集,而不是单个结果集中。
按照第 3 点,将您的联合查询调整为引用 table,其列顺序在结果中是预期的。
您可以使用 STRING_AGG
两次以获得 UNION ALL
。您可以通过 string_agg
.
column_name
显式排序来按特定顺序获取所有列
这是一个通用函数,它采用 table 数组和最终的 table 名称。
CREATE or replace FUNCTION fn_create_tab(tname_arr TEXT[], p_tab_name TEXT)
RETURNS VOID AS $$
DECLARE
l_select TEXT;
BEGIN
select STRING_AGG(query,' UNION ALL ' ) INTO l_select
FROM
(
SELECT 'select ' || string_agg( column_name,','
ORDER BY column_name ) || ' from ' || table_name as query
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = ANY (tname_arr)
GROUP BY table_name
) s;
IF l_select IS NOT NULL
THEN
EXECUTE format ('DROP TABLE IF EXISTS %I',p_tab_name);
EXECUTE format ('create table %I AS %s',p_tab_name,l_select);
END IF;
END;
$$ LANGUAGE plpgsql;
现在,运行函数如下:
select fn_create_tab(ARRAY['huiwen','penglai'],'sum_2018_xia_weijian');