在PostgreSQL中,我有一个表country
和一个表property
。一个国家可以拥有很多房产。每个属性都有created_at
。我需要计算按年和周分隔的每个国家/地区的属性。就像一个例子,我有一个国家的查询。
SELECT
EXTRACT(YEAR FROM created_at) AS yy,
EXTRACT(WEEK FROM created_at) AS week,
COUNT(id) AS country_1
FROM property
WHERE id_country = 1
GROUP BY week, yy
ORDER BY yy, week ASC
结果是这样的
yy |week|country_1
---------------
2014|1 |5
2014|2 |1154
2014|3 |769
...
所以,我需要这样的结果
yy |week|country_1|country_2|country_3
----------------------------------------
2014|1 |5 |56 |543
2014|2 |1154 |1234 |432
2014|3 |769 |123 |432
...
这可能吗?,查询怎么样?
答案 0 :(得分:2)
您可以使用crosstab()
功能(在tablefunc
扩展名中)来解决此问题,该功能会转动您的数据。不幸的是,该功能只能在一个列上进行旋转,因此您必须稍微捏一下您的数据,然后取消它以获得所需的结果。
首先是软糖,而不是像这样产生两列:
extract(year from created_at) AS yy,
extract(week from created_at) AS week
你应该将它们放在一个列中,如下所示:
extract(year from created_at) * 100 + extract(week from created_at) AS yr_wk
为您提供类似201401, 201402, 201403
等的值。不错的属性是,它们就像单独的年份和周值一样排序,它们很容易组装,然后反汇编。
接下来,您运行crosstab()
功能:
SELECT * FROM crosstab(
'SELECT extract(year from created_at) * 100 + extract(week from created_at) AS yr_wk,
id_country, count(id) AS cnt
FROM property GROUP BY 1, 2 ORDER BY 1, 2',
'SELECT s FROM generate_series(1, 7) s'
) AS (yr_wk int, c1 int, c2 int, c3 int, c4 int, c5 int, c6 int, c7 int);
其中' c1' - ' c7'是您所在国家/地区的名称。
然后填写你所做的yr_wk
值:
SELECT yr_wk / 100 AS yy, yr_wk % 100 AS week, c1, c2, c3, c4, c5, c6, c7
FROM (
<< crosstab query from above >>
) sub
ORDER BY 1, 2;
答案 1 :(得分:2)
没有任何扩展的替代解决方案:
bower cache clean
如果您使用的是pg 9.4或更高版本,则可以替换
>= 1.0.8
与
SELECT
EXTRACT(YEAR FROM created_at) AS yy,
EXTRACT(WEEK FROM created_at) AS week,
COUNT(CASE WHEN id_country = 1 THEN id ELSE null END) AS country_1,
COUNT(CASE WHEN id_country = 2 THEN id ELSE null END) AS country_2,
COUNT(CASE WHEN id_country = 3 THEN id ELSE null END) AS country_3,
...
COUNT(CASE WHEN id_country = 7 THEN id ELSE null END) AS country_7,
FROM property
GROUP BY week, yy
ORDER BY yy, week ASC;
等等。