视图中的动态列名称(Postgres)

时间:2012-02-27 15:05:44

标签: sql postgresql relational-database

我目前正在编写一个SQL视图,它应该提供特定月份的填充字段数。

这就是我希望构建视图的方式:

Country   | (Current Month - 12) Eg Feb 2011 | (Current Month - 11) | (Current Month - 10)
----------|----------------------------------|----------------------|---------------------
UK        | 10                               | 11                   | 23

月份下的数字应该是特定国家/地区的所有填充字段的数量。该字段名为eldate,是格式为10-12-2011的日期(转换为字符)。我希望计数只计算与月份匹配的日期。

因此,“当前月份 - 12”列应仅包括在此之前12个月内的日期计数。例如,本月 - 英国的12个应包括2011年2月之内的日期计数。

我希望列标题能够真正反映它所看到的月份:

Country | Feb 2011 | March 2011 | April 2011
--------|----------|------------|------------
UK      | 4        | 12         | 0

类似于:

SELECT c.country_name,
        (SELECT COUNT("C1".eldate) FROM "C1" WHERE "C1".eldate LIKE %NOW()-12 Months% AS NOW() - 12 Months
        (SELECT COUNT("C1".eldate) FROM "C1" WHERE "C1".eldate LIKE %NOW()-11 Months% AS NOW() - 11 Months
FROM country AS c
INNER JOIN "site" AS s using (country_id)
INNER JOIN "subject_C1" AS "C1" ON "s"."site_id" = "C1"."site_id"

显然这不起作用,只是为了让你了解我的目标。

有什么想法吗?

感谢您的帮助,请再询问。

2 个答案:

答案 0 :(得分:2)

我的第一个倾向是制作这张桌子:

+---------+-------+--------+
| Country | Month | Amount |
+---------+-------+--------+
| UK      | Jan   | 4      |
+---------+-------+--------+
| UK      | Feb   | 12     |
+---------+-------+--------+

等。转动它。所以你从(例如)开始:

SELECT 
  c.country, 
  EXTRACT(MONTH FROM s.eldate) AS month, 
  COUNT(*) AS amount
FROM country AS c
JOIN site AS s ON s.country_id = c.id
WHERE 
  s.eldate > NOW() - INTERVAL '1 year'
GROUP BY c.country, EXTRACT(MONTH FROM s.eldate);

然后您可以将其插入one the crosstab functions from the tablefunc module以实现支点,执行以下操作:

SELECT * 
FROM crosstab('<query from above goes here>') 
  AS ct(country varchar, january integer, february integer, ... december integer);

答案 1 :(得分:1)

您可以截断日期以进行比较:

WHERE date_trunc('month', eldate) = date_trunc('month', now()) - interval '12 months'

更新

这种替代您的查询:

(SELECT COUNT("C1".eldate) FROM "C1" WHERE date_trunc('month', "C1".eldate) =
    date_trunc('month', now()) - interval '12 months') AS TWELVE_MONTHS_AGO

但是这会涉及每个月扫描一次表格,所以你可以用这些方式进行一次扫描:

SELECT SUM( CASE WHEN date_trunc('month', "C1".eldate) =  date_trunc('month', now()) - interval '12 months' THEN 1 ELSE 0 END ) AS TWELVE_MONTHS_AGO
      ,SUM( CASE WHEN date_trunc('month', "C1".eldate) =  date_trunc('month', now()) - interval '11 months' THEN 1 ELSE 0 END ) AS ELEVEN_MONTHS_AGO
...

或者像其他人一样在几个月的表格中加入。

UPDATE2

除了关于修复从1月到12月的列的评论之外,我还在考虑这样的事情:过滤最近几年的记录,然后在适当的月份总结。也许是这样的:

SELECT SUM( CASE WHEN EXTRACT(MONTH FROM "C1".eldate) = 1 THEN 1 ELSE 0 END ) AS JAN
      ,SUM( CASE WHEN EXTRACT(MONTH FROM "C1".eldate) = 2 THEN 1 ELSE 0 END ) AS FEB
      ...

  WHERE date_trunc('month', "C1".eldate) <  date_trunc('month', now())
    AND date_trunc('month', "C1".eldate) >= date_trunc('month', now()) - interval '12 months'