2012-02-27 17 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

+0

ええ、私はそれがおそらく方法だと思っていましたが、私は初心者であり、これを行うための関数 –

答えて

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 

しかし、それはテーブルのスキャンを伴うだろうが1か月に1回スキャンすることができます。

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 
... 

他の人が表示しているように月のテーブルを使って結合するか、その後、適切な月に合計、レコードの価値は最後の年のフィルタ:さらに12月に月から列を固定にコメントへのアップデート2

は、私はこのような何かを考えていました。おそらく、このように:

+---------+-------+--------+ 
| Country | Month | Amount | 
+---------+-------+--------+ 
| UK  | Jan | 4  | 
+---------+-------+--------+ 
| UK  | Feb | 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

さらに説明できますか? –

+0

これは良い働きをしてくれますが、列に実際に動的に名前を付ける方法はありませんか? –

+0

@AydinHassan私が認識しているわけではありません。この場合、私は列(JAN - DEC)を固定することに腰を傾け、ハードコーディングされた-12、-11、...ではなく、now()-jan、now() - febなどを含む数学を行います。年の境界線を扱う必要がありますが、それはおそらく最小/最大のものです。 – Glenn

2

私の最初の傾斜は、このテーブルを生成することです。だから、(例えば)で始めたい:

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

私はあなたが何を意味するのか分かりませんが、助けてくれてありがとうございます。 –

+0

@AydinHassan何がハングアップですか? –