2012-02-27 55 views
1

我目前正在编程一个SQL视图应该提供一个特定月份的填充字段的计数。动态列名称在视图(Postgres)

这是我想建造的观点:

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

月份下的数字应该是某个国家的所有填充字段的计数。该字段被命名为eldate,并且是格式为10-12-2011的日期(格式为char)。我希望计数只计算与月份相匹配的日期。

因此,“当前月份 - 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" 

显然,这并不工作,但只给你一个关于我所得到的想法。

任何想法?

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

+1

我不知道你是否能实现这与一个观点,但你可以使用一个功能。注意PostgreSQL中你可以调用这样的函数:'SELECT * FROM funName()' – DavidEG 2012-02-27 15:12:43

+0

是的,我认为这可能是一种方式,然而,我是一个新手,不知道如何构建一个函数来做到这一点 – 2012-02-27 15:17:15

回答

1

你可以截断日期使可比性:

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

UPDATE

这种替代你的查询:

(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

继从一月列固定至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' 
+0

请你再解释一下吗? – 2012-02-27 15:49:20

+0

好的,这很好,谢谢,但是没有办法实际动态地命名列? – 2012-02-27 16:15:52

+0

@AydinHassan不是我所知道的。在这种情况下,我会倾向于固定列(JAN - DEC),然后做一些涉及now() - 1an,now() - feb等的数学,而不是硬编码的-12,-11。 。需要对年份边界进行一些处理,但这可能是一些最小/最大值的东西。 – Glenn 2012-02-27 16:27:23

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); 
+0

我不知道我明白你的意思,但感谢您的帮助 – 2012-02-28 09:03:12

+0

@AydinHassan什么是挂断? – 2012-02-28 15:19:57