PostgreSQL交叉表函数

PostgreSQL交叉表函数,sql,postgresql,pivot,crosstab,Sql,Postgresql,Pivot,Crosstab,我对交叉表函数有一些问题 我的桌子“t”是空的 我想要这个“透视表”t\u透视图 Sql代码是 SELECT * from crosstab ( 'SELECT day,name,hour,cause, SUM(c_p) AS c_p FROM t GROUP BY 1,2,3,4 ORDER BY 3 ', 'SELECT DISTINCT cause FROM i ORDER BY

我对交叉表函数有一些问题

我的桌子“t”是空的

我想要这个“透视表”t\u透视图

Sql代码是

SELECT  * from crosstab (
    'SELECT  day,name,hour,cause, SUM(c_p) AS c_p
        FROM t
        GROUP BY 1,2,3,4
        ORDER BY 3 ',

     'SELECT DISTINCT cause 
         FROM i
         ORDER BY 1')

AS t_pivot (day date, name integer,hour integer, cause_0 integer,cause_1 integer)
查询结果是一行表,取决于“订单依据”

错误在哪里? 谢谢
f、

我没有使用过
交叉表
函数,现在无法测试它(sqlfiddle上没有tablefunc扩展),但一般来说,如果我需要这样的数据透视,我更喜欢简单的SQL:

select
    date,
    hour,
    sum(case when cause = 0 then c_p else 0 end) cause_0,
    sum(case when cause = 1 then c_p else 0 end) cause_1
from t
group by date, hour
order by hour

我认为以后维护和阅读它会更容易(但这是主观的观点)

更新这一行有效(小时用作
行名称
,日期和名称为
额外的
列):

发件人:

source_sql是生成数据源集的sql语句。 此语句必须返回一行\名称列、一个类别列、, 和一个值列。它还可能有一个或多个“额外”列。 “行名称”列必须位于第一位。类别和值列必须 请按该顺序显示最后两列。行和名称之间的任何列 和类别被视为“额外”。需要“额外”列 对于具有相同行名称值的所有行都相同

在实践中,源sql查询应始终指定ORDER BY 1到 确保将具有相同行名称的值放在一起。 然而,组内类别的排序并不重要。 此外,必须确保类别的顺序 查询的输出与指定的输出列顺序匹配


似乎
crosstab
函数只希望有一列保存行标识,如果我没有弄错的话,您有三列:day、name和hour。但是,
交叉表
也允许额外的列,它不会将其视为特殊的,它只是将其添加到结果中

因此,对于您的案例,您必须获得这三列,并将它们表示为一列。我不确定这是否是最好的方法,但我使用了
构造函数来实现这一点(因此我们不需要关心数据类型):

这将产生如下结果:

      row_name       |    day     | hour | name | cause_0 | cause_1 
---------------------+------------+------+------+---------+---------
 (2013-06-12,14,167) | 2013-06-12 |   14 |  167 |       2 |      --
 (2013-06-12,16,167) | 2013-06-12 |   16 |  167 |       7 |      --
 (2013-06-12,19,167) | 2013-06-12 |   19 |  167 |       4 |       1
 (2013-06-13,14,167) | 2013-06-13 |   14 |  167 |      10 |      --
(4 rows)
您不必担心第一列,它实际上对您毫无用处,因此我们可以将其删除:

SELECT day,hour,name,cause_0,cause_1 FROM (SELECT  * from crosstab (
    'select row(day,hour,name),day, hour, name, cause, sum(c_p) as c_p
     from t
     group by 2, 3, 4, 5
     order by 1',
    'VALUES(0),(1)')
AS t_pivot (row_name text, day date, hour int, name integer, cause_0 integer,cause_1 integer)) AS t;

还有一件事。请注意,我在第二个参数中使用了
,而不是
选择不同的值
,如果您确定这些值是唯一可用的值(如果它不是静态的),则这是一种更好的方法,然后
作为t\u轴…
也应该是动态的。

是的,但我必须使用交叉表,因为这是一个更复杂的示例table@user2418290见更新,仍需阅读文档以了解其为何如此运行我认为这与OP的预期不太相符,因为若你们在不同的日子里插入相同的小时,它将产生一个不一致的结果。+1从手机上读到你们的评论,并考虑使用行作为第一列,但你们已经这样做了。我仍然更喜欢使用group by的手动轴:)
select
    date,
    hour,
    sum(case when cause = 0 then c_p else 0 end) cause_0,
    sum(case when cause = 1 then c_p else 0 end) cause_1
from t
group by date, hour
order by hour
SELECT  * from crosstab (
    'select hour, date, name, cause, sum(c_p) as c_p
     from t
     group by 1, 2, 3, 4
     order by 1',
    'select distinct cause from t order by 1')
AS t_pivot (hour integer, date timestamp, name integer, cause_0 integer,cause_1 integer)
SELECT  * from crosstab (                                           
    'select row(day,hour,name),day, hour, name, cause, sum(c_p) as c_p
     from t
     group by 2, 3, 4, 5
     order by 1',
    'VALUES(0),(1)')
AS t_pivot (row_name text, day date, hour int, name integer, cause_0 integer,cause_1 integer);
      row_name       |    day     | hour | name | cause_0 | cause_1 
---------------------+------------+------+------+---------+---------
 (2013-06-12,14,167) | 2013-06-12 |   14 |  167 |       2 |      --
 (2013-06-12,16,167) | 2013-06-12 |   16 |  167 |       7 |      --
 (2013-06-12,19,167) | 2013-06-12 |   19 |  167 |       4 |       1
 (2013-06-13,14,167) | 2013-06-13 |   14 |  167 |      10 |      --
(4 rows)
SELECT day,hour,name,cause_0,cause_1 FROM (SELECT  * from crosstab (
    'select row(day,hour,name),day, hour, name, cause, sum(c_p) as c_p
     from t
     group by 2, 3, 4, 5
     order by 1',
    'VALUES(0),(1)')
AS t_pivot (row_name text, day date, hour int, name integer, cause_0 integer,cause_1 integer)) AS t;