inv*_*c4u 19 postgresql dynamic-sql crosstab plpgsql postgresql-9.1
我试图crosstab在PostgreSQL中创建查询,以便它自动生成crosstab列而不是硬编码.我编写了一个函数,可以动态生成我的crosstab查询所需的列列表.我们的想法是crosstab使用动态sql 在查询中替换此函数的结果.
我知道如何在SQL Server中轻松完成这项工作,但我对PostgreSQL的了解有限,阻碍了我在这方面的进展.我正在考虑将生成动态列列表的函数结果存储到变量中,并使用它来动态构建sql查询.如果有人可以指导我这样做会很棒.
-- Table which has be pivoted
CREATE TABLE test_db
(
    kernel_id int,
    key int,
    value int
);
INSERT INTO test_db VALUES
(1,1,99),
(1,2,78),
(2,1,66),
(3,1,44),
(3,2,55),
(3,3,89);
-- This function dynamically returns the list of columns for crosstab
CREATE FUNCTION test() RETURNS TEXT AS '
DECLARE
    key_id int;
    text_op TEXT = '' kernel_id int, '';
BEGIN
    FOR key_id IN SELECT DISTINCT key FROM test_db ORDER BY key LOOP
    text_op := text_op || key_id || '' int , '' ;
    END LOOP;
    text_op := text_op || '' DUMMY text'';
    RETURN text_op;
END;
' LANGUAGE 'plpgsql';
-- This query works. I just need to convert the static list
-- of crosstab columns to be generated dynamically.
SELECT * FROM
crosstab
(
    'SELECT kernel_id, key, value FROM test_db ORDER BY 1,2',
    'SELECT DISTINCT key FROM test_db ORDER BY 1'
)
AS x (kernel_id int, key1 int, key2 int, key3 int); -- How can I replace ..
-- .. this static list with a dynamically generated list of columns ?
Erw*_*ter 13
您可以使用提供的C函数crosstab_hash.
手册在这方面不是很清楚.本章末尾提到了两个参数:crosstab()
您可以创建预定义函数,以避免在每个查询中写出结果列名称和类型.请参阅上一节中的示例.这种形式的底层C函数
crosstab被命名crosstab_hash.
对于你的例子:
CREATE OR REPLACE FUNCTION f_cross_test_db(text, text)
  RETURNS TABLE (kernel_id int, key1 int, key2 int, key3 int)
  AS '$libdir/tablefunc','crosstab_hash' LANGUAGE C STABLE STRICT;
呼叫:
SELECT * FROM f_cross_test_db(
      'SELECT kernel_id, key, value FROM test_db ORDER BY 1,2'
     ,'SELECT DISTINCT key FROM test_db ORDER BY 1');
请注意,您需要为具有不同返回类型的crosstab_hash每个crosstab函数创建一个不同的函数.
你的功能,生成列清单是颇为曲折,其结果是不正确的(int失踪kernel_id),就可以用这个SQL查询替换:
SELECT 'kernel_id int, '
       || string_agg(DISTINCT key::text, ' int, '  ORDER BY key::text)
       || ' int, DUMMY text'
FROM   test_db;
并且它无论如何都不能动态使用.
我意识到这是一篇较旧的帖子,但在同一问题上挣扎了一段时间。
我的问题陈述: 我有一个字段中包含多个值的表,并且想要创建一个每行包含 40 多个列标题的交叉表查询。
我的解决方案是创建一个函数,该函数循环遍历表列以获取我想在交叉表查询中用作列标题的值。
在这个函数中,我可以创建交叉表查询。在我的用例中,我将此交叉表结果添加到单独的表中。
例如
CREATE OR REPLACE FUNCTION field_values_ct ()
 RETURNS VOID AS $$
DECLARE rec RECORD;
DECLARE str text;
BEGIN
str := '"Issue ID" text,';
   -- looping to get column heading string
   FOR rec IN SELECT DISTINCT field_name
        FROM issue_fields
        ORDER BY field_name
    LOOP
    str :=  str || '"' || rec.field_name || '" text' ||',';
    END LOOP;
    str:= substring(str, 0, length(str));
    EXECUTE 'CREATE EXTENSION IF NOT EXISTS tablefunc;
    DROP TABLE IF EXISTS temp_issue_fields;
    CREATE TABLE temp_issue_fields AS
    SELECT *
    FROM crosstab(''select issue_id, field_name, field_value from issue_fields order by 1'',
                 ''SELECT DISTINCT field_name FROM issue_fields ORDER BY 1'')
         AS final_result ('|| str ||')';
END;
$$ LANGUAGE plpgsql;
| 归档时间: | 
 | 
| 查看次数: | 21654 次 | 
| 最近记录: |