将查询中的聚合值INSERT到SQL中的表中

时间:2012-03-15 14:30:37

标签: postgresql aggregate-functions

我是SQL新手,通过反复试验以及搜索书籍和互联网进行了大量工作。我必须重复查询五年的月度数据总和,并且我想将每个月的结果作为一个列插入表中。我尝试每个月添加新列

alter table add column, insert etc.

但我无法做对。这是我用于jan和feb07的代码:

CREATE TABLE "TVD_db"."lebendetiere"
(nuar text,
ak text,
sex text,
jan07 text,
feb07 text,
märz07 text,
april07 text,
mai07 text,
juni07 text,
juli07 text, 
aug07 text,
sept07 text,
okt07 text,
nov07 text,
dez07 text,
jan08 text,
....
dez11 text);


INSERT INTO "TVD_db"."lebendetiere" (nuar, ak, sex, jan07)
SELECT
"AUFENTHALTE"."nuar",
CASE WHEN DATE ('2007-01-01')- DATE ("AUFENTHALTE"."gebdat") < 365 THEN '1' WHEN   DATE('2007-01-01')- DATE ("AUFENTHALTE"."gebdat") > 730 THEN 3 ELSE 2 END AS AK,
CASE WHEN "AUFENTHALTE"."isweiblich" = 'T' THEN 'female' ELSE 'male' END AS sex,
COUNT("AUFENTHALTE"."tierid")
FROM "TVD_db"."AUFENTHALTE"
WHERE DATE("AUFENTHALTE"."gueltigvon") <= DATE('2007-01-01')
AND DATE("AUFENTHALTE"."gueltigbis") >= DATE('2007-01-01')
GROUP BY "AUFENTHALTE"."nuar",
CASE WHEN DATE ('2007-01-01')- DATE ("AUFENTHALTE"."gebdat") < 365 THEN '1' WHEN DATE  ('2007-01-01')- DATE ("AUFENTHALTE"."gebdat") > 730 THEN 3 ELSE 2 END,
CASE WHEN "AUFENTHALTE"."isweiblich" = 'T' THEN 'female' ELSE 'male' END
ORDER BY "AUFENTHALTE"."nuar",
CASE WHEN DATE ('2007-01-01')- DATE ("AUFENTHALTE"."gebdat") < 365 THEN '1' wWHEN DATE ('2007-01-01')- DATE ("AUFENTHALTE"."gebdat") > 730 THEN 3 ELSE 2 END,
CASE WHEN "AUFENTHALTE"."isweiblich" = 'T' THEN 'female' ELSE 'male' END
;

- 直到这里工作正常

UPDATE  "TVD_db"."lebendetiere" SET "feb07"= --this is the part I cant get right...
(SELECT
COUNT("AUFENTHALTE"."tierid")
FROM "TVD_db"."AUFENTHALTE"
WHERE DATE("AUFENTHALTE"."gueltigvon") <= DATE('2007-02-01')
AND DATE("AUFENTHALTE"."gueltigbis") >= DATE('2007-02-01')
GROUP BY "AUFENTHALTE"."nuar",
CASE WHEN DATE ('2007-02-01')- DATE ("AUFENTHALTE"."gebdat") < 365 THEN '1' WHEN DATE ('2007-02-01')- DATE ("AUFENTHALTE"."gebdat") > 730 THEN 3 ELSE 2 END,
CASE WHEN "AUFENTHALTE"."isweiblich" = 'T' THEN 'female' ELSE 'male' END
ORDER BY "AUFENTHALTE"."nuar",
CASE WHEN DATE ('2007-01-01')- DATE ("AUFENTHALTE"."gebdat") < 365 THEN '1' wWHEN DATE ('2007-01-01')- DATE ("AUFENTHALTE"."gebdat") > 730 THEN 3 ELSE 2 END,
CASE WHEN "AUFENTHALTE"."isweiblich" = 'T' THEN 'female' ELSE 'male' END);

有没有人有解决方案,或者我必须每个月制作一张桌子,然后加入结果?

1 个答案:

答案 0 :(得分:2)

在仔细阅读完您的帖子之后,这里有一个完全重新设计,它应该为SQL / PostgreSQL领域的初学者提供一些见解。

  • 我建议不要使用大小写identifiers in PostgreSQL。单独使用小写,然后您不必重复引用它们,您的代码更容易阅读。你也避免了很多混乱。

  • 使用table aliases使您的代码更具可读性。

  • INSERT的SELECT语句中的列名无关紧要。这就是我之后发表评论的原因(避免可能的命名冲突)。

  • 使用GROUP BY和ORDER BY中的序号进一步简化。

  • 每个新月都不要使用单独的列。使用标识月份的列并每月添加一行 如果您确实需要每月一列的设计,那么您需要一个大型CASE语句或数据透视查询。请参阅tablefunc扩展程序。但对于SQL新手来说,这是一件复杂的事情。我真的认为,你想要每月一排。

  • 我使用generate_series()在2007年1月至2011年12月期间每月生成一行。

  • 使用我更改的设计,您不需要额外的更新。这一切都在一个INSERT中完成。

我简化了其他几件事。以下是我的建议:

CREATE TABLE tvd_db.lebendetiere(
  nuar text,
 ,alterskat integer
 ,sex text
 ,datum date
 ,anzahl integer
 );

INSERT INTO tvd_db.lebendetiere (nuar, alterskat, sex, datum, anzahl)
SELECT a.nuar
      ,CASE WHEN a.gebdat >= '2006-01-01'::date THEN 1 -- use >= !
            WHEN a.gebdat <  '2005-01-01'::date THEN 3
            ELSE                                     2 END -- AS alterskat
      ,CASE WHEN a.isweiblich = 'T' THEN 'female' ELSE 'male' END -- AS sex
      ,m.m
      ,count(*) -- AS anzahl
FROM   tvd_db.aufenthalte a
CROSS  JOIN (
    SELECT generate_series('2007-01-01'::date
                          ,'2011-12-01'::date, interval '1 month')::date
    ) m(m)
WHERE  a.gueltigvon <= m.m
AND    a.gueltigbis >= m.m
GROUP  BY a.nuar, 2, 3, m.m
ORDER  BY a.nuar, 2, 3, m.m;