crosstab()
具有两个参数的功能。
应该像这样工作,以获取2012年的价值:
SELECt * FROM crosstab( $$SELECt testname, to_char(last_update, 'mon_YYYY'), count(*)::int AS ct FROM tests WHERe current_status = 'FAILED' AND last_update >= '2012-01-01 0:0' AND last_update < '2013-01-01 0:0' -- proper date range! GROUP BY 1,2 ORDER BY 1,2$$ ,$$VALUES ('jan_2012'::text), ('feb_2012'), ('mar_2012') , ('apr_2012'), ('may_2012'), ('jun_2012') , ('jul_2012'), ('aug_2012'), ('sep_2012') , ('oct_2012'), ('nov_2012'), ('dec_2012')$$)AS ct (testname text , jan_2012 int, feb_2012 int, mar_2012 int , apr_2012 int, may_2012 int, jun_2012 int , jul_2012 int, aug_2012 int, sep_2012 int , oct_2012 int, nov_2012 int, dec_2012 int);在此相关问题下找到详细说明。
我没有测试。 正如@Craig所说,样本值会有所帮助。
现在使用我自己的测试用例进行了测试。
不显示NULL值
crosstab()具有两个参数的函数避免了主要问题(根本不会出现没有行的月份)。
您不能
COALESCE在内部查询中使用,因为这些
NULL值是
crosstab()自己插入的。你可以 …
1.将整个内容包装到一个子查询中:
SELECT testname ,COALESCE(jan_2012, 0) AS jan_2012 ,COALESCE(feb_2012, 0) AS feb_2012 ,COALESCE(mar_2012, 0) AS mar_2012 , ...FROM ( -- query from above) ) x;
2.LEFT JOIN
主要查询到完整的月份列表。
在这种情况下,根据定义,您不需要第二个参数。
对于更大的范围,您可以使用
generate_series()创建值。
SELECt * FROM crosstab( $$SELECt t.testname, m.mon, count(x.testname)::int AS ct FROM ( VALUES('jan_2012'::text), ('feb_2012'), ('mar_2012') ,('apr_2012'), ('may_2012'), ('jun_2012') ,('jul_2012'), ('aug_2012'), ('sep_2012') ,('oct_2012'), ('nov_2012'), ('dec_2012') ) m(mon) CROSS JOIN (SELECt DISTINCT testname FROM tests) t LEFT JOIN ( SELECt testname ,to_char(last_update, 'mon_YYYY') AS mon FROM tests WHERe current_status = 'FAILED' AND last_update >= '2012-01-01 0:0' AND last_update < '2013-01-01 0:0' -- proper date range! ) x USING (mon) GROUP BY 1,2 ORDER BY 1,2$$ )AS ct (testname text , jan_2012 int, feb_2012 int, mar_2012 int , apr_2012 int, may_2012 int, jun_2012 int , jul_2012 int, aug_2012 int, sep_2012 int , oct_2012 int, nov_2012 int, dec_2012 int);带有样本数据的测试用例
这是一个测试案例,其中包含一些OP无法提供的示例数据。我用它来测试它并使它工作。
CREATE TEMP TABLE tests ( id bigserial PRIMARY KEY ,testname text NOT NULL ,last_update timestamp without time zone NOT NULL DEFAULT now() ,current_status text NOT NULL );INSERT INTO tests (testname, last_update, current_status)VALUES ('foo', '2012-12-05 21:01', 'FAILED') ,('foo', '2012-12-05 21:01', 'FAILED') ,('foo', '2012-11-05 21:01', 'FAILED') ,('bar', '2012-02-05 21:01', 'FAILED') ,('bar', '2012-02-05 21:01', 'FAILED') ,('bar', '2012-03-05 21:01', 'FAILED') ,('bar', '2012-04-05 21:01', 'FAILED') ,('bar', '2012-05-05 21:01', 'FAILED');


