2

我有两个表,其简化结构如下所示:

RESPONSES
id
created

ACCESSORY VALUES
id
response_id
sensor_id
value

我想创建一个视图,将给定响应的所有附件值在一段时间内扁平化为一行(过滤response.created)。我想我想要一个数据透视表或交叉表,但我对两者都不熟悉,而且我发现的示例主要处理已知数量的列。更复杂的是,如果用户在相关时间段内开始或停止跟踪某个给定的传感器,它只能在部分时间段内出现。理想情况下,当传感器不存在时,我会在该列中为任何行中的传感器保留一个 NULL。这可能吗?如果是这样,我是在正确的轨道上还是在错误的地方寻找?

将数据作为单个行获取的 SQL 看起来像

SELECT r.id, a.sensor_id, a.value from results_response r 
INNER JOIN results_accessoryvalue a ON r.id = a.response_id
WHERE r.installation_id = 40 
AND r.created BETWEEN '2013-04-01' AND '2013-05-01' 
ORDER BY r.created

但我没有任何运气尝试在交叉表中使用它,因为我不知道如何指定动态列。

4

2 回答 2

3

您应该使用带有一些附加功能的交叉表。我也有这个问题,并为我的提案解决了这个问题。

首先安装交叉表扩展

我使用的技巧是创建 2 个附加功能。一个获取类型信息,需要作为交叉表函数的结果集。看这个:

CREATE OR REPLACE FUNCTION "TEMPORARY.TYPE.FROM.COLUMN"(text, text)
  RETURNS text AS
$BODY$
DECLARE
    typestring TEXT;
    returnrec RECORD;
BEGIN
    typestring := '';
    FOR returnrec IN EXECUTE $1 LOOP
        typestring := typestring||', "'||returnrec."Column"||'" '||$2;
    END LOOP;

  RETURN typestring;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

现在我们可以编写第二个函数:

CREATE OR REPLACE FUNCTION "DYNAMIC.CROSSTAB"(text, text, text)
  RETURNS text AS
$BODY$
DECLARE
    typestring TEXT;
    executestring TEXT;
BEGIN
    DROP TABLE IF EXISTS "TBL.Crosstab";
    SELECT "REPORTING"."TEMPORARY.TYPE.FROM.COLUMN"($2,$3) INTO typestring;
    executestring := 'CREATE TEMPORARY TABLE "TBL.Crosstab" AS (SELECT * FROM crosstab('''||$1||''','''||$2||''') AS (row_name DATE'||typestring||'));';
    EXECUTE executestring;
  RETURN '"TBL.Crosstab"';
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

要创建交叉表,只需调用:

SELECT * FROM "DYNAMIC.CROSSTAB"(text, text, text);

它为您的会话返回一个临时表的名称,其中填充了您的结果。我需要这种方式。

参数说明:

First = 获取数据的查询(必须有 3 列:row_name、cat 和 value)

第二=获取您的列的查询返回所有类别(猫)

第三 = 我们的临时类型的列类型

它并不完美,但符合我们的需求。我们有语句,以这种方式获取超过 450 列和一些 thounds 行。希望能帮助到你

于 2013-05-15T10:49:54.393 回答
0

这是使用 PostgreSQL 数组的另一种方法

create table responses (
    id serial not null  unique,
    x   integer,
    created timestamp default now()
);

 create table accessory (
    id serial not null,
    responses_id integer references responses (id),
    sensor_id  integer,
    value text,
    created timestamp default now()
);

insert into responses  (x) values  ( 1), (2),(3),(4);

insert into accessory  (responses_id ,  sensor_id, value ) values  
( 1, 1, 'A' ), ( 1, 2, 'Ab' ),  ( 1, 3, 'Ac' ),  ( 1, 4, 'Ad' ),
( 2, 4, 'Ab' ), ( 1, 2, 'bAb' ),  ( 3, 3, 'bAc' ),  ( 4, 4, 'bAd' );

select *, array(
    select value
    from accessory
    where accessory.responses_id  = responses.id  
    order by  accessory.created
    ) as accessory_values
from responses;

查询结果包含一个数组列,其中包含与 response.id 匹配的所有附件值

于 2013-05-10T18:13:10.137 回答