ale*_*smn 4 postgresql view functions
目前我创建了一个视图,请在答案中查看。如何根据该crosstab()查询创建函数,以便传递日期并获取特定日期的数据?
多次调用该函数并传递不同的日期来填充图表(例如)也是一种好习惯吗?
Erw*_*ter 12
我建议使用 SQL 函数:
CREATE OR REPLACE FUNCTION foo(_date date)
RETURNS TABLE (
name text -- types have to match your actual types!
, keyword_id int
, project_id int
, the_date date
, today int
, yesterday int
, week int
, month int) AS
$func$
SELECT k.name, f.keyword_id, f.project_id, _date -- AS the_date -- col alias irrelevant
, f.t AS today, f.y As yesterday, f.w AS week, f.m AS month
FROM crosstab(
-- crosstab function from previous question here
-- http://dba.stackexchange.com/a/71266/3684
) f (rn int, keyword_id int, project_id int
, t int, y int, w int, m int)
JOIN keyword k USING (keyword_id);
$func$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)
称呼:
SELECT * FROM foo('2014-07-07');
Run Code Online (Sandbox Code Playgroud)
用now()::date名为 的输入参数替换所有出现的_date。
在 Postgres 9.1 或更早版本中,$1在 SQL 函数中使用位置参数(可以在任何版本中使用)。
更多代码示例:
该crosstab()函数将查询字符串作为参数。函数参数在里面是不可见的crosstab()。所以你需要将日期值作为字符串文字传递!为方便起见,
我建议使用该功能format()。例如,第二个参数变为:
,format('VALUES(%L::date), (%L), (%L), (%L)'
, $1, $1 - 1, $1 - 7, ($1 - interval '1 month')::date
)
Run Code Online (Sandbox Code Playgroud)
代替:
,$$
VALUES
(now()::date)
, (now()::date - 1)
, (now()::date - 7)
, ((now() - interval '1 month')::date)
$$
Run Code Online (Sandbox Code Playgroud)
CREATE OR REPLACE FUNCTION foo_sql(_date date)
RETURNS TABLE (
name text
, keyword_id int
, project_id int
, the_date date
, today int
, yesterday int
, week int
, month int) AS
$func$
BEGIN
SELECT k.name, f.keyword_id, f.project_id, _date
, f.t, f.y, f.w, f.m
FROM crosstab (
$$
SELECT rn
, pk.keyword_id
, pk.project_id
, d.created_at
, COALESCE(pr.pos, 0)
FROM (SELECT *, row_number() OVER () AS rn FROM project_keyword) pk
CROSS JOIN (
$$
|| format('VALUES(%L::date), (%L), (%L), (%L)'
, $1, $1 - 1, $1 - 7, ($1 - interval '1 month')::date)
|| $$
) d(created_at)
LEFT JOIN (
SELECT keyword_id
, project_id
, created_at::date AS created_at
, min(position) AS pos
FROM project_report
GROUP BY keyword_id, project_id, created_at::date
) pr USING (keyword_id, project_id, created_at)
ORDER BY pk.rn, d.created_at
$$
,format('VALUES(%L::date), (%L), (%L), (%L)'
, $1, $1 - 1, $1 - 7, ($1 - interval '1 month')::date)
) f (rn int, keyword_id int, project_id int
, t int, y int, w int, m int)
JOIN keyword k USING (keyword_id);
END
$func$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)
更短,重用VALUES表达式。也可能快一点。
CREATE OR REPLACE FUNCTION foo_plpgsql(_date date)
RETURNS TABLE (name text, keyword_id int, project_id int, the_date date
, today int, yesterday int, week int, month int) AS
$func$
DECLARE
_dates text := format('VALUES(%L::date), (%L), (%L), (%L)'
, $1, $1 - 1, $1 - 7, ($1 - interval '1 month')::date);
BEGIN
SELECT k.name, f.keyword_id, f.project_id, _date, f.t, f.y, f.w, f.m
FROM crosstab (
'SELECT rn
, pk.keyword_id
, pk.project_id
, d.created_at
, COALESCE(pr.pos, 0)
FROM (SELECT *, row_number() OVER () AS rn FROM project_keyword) pk
CROSS JOIN (
' || _dates || '
) d(created_at)
LEFT JOIN (
SELECT keyword_id
, project_id
, created_at::date AS created_at
, min(position) AS pos
FROM project_report
GROUP BY keyword_id, project_id, created_at::date
) pr USING (keyword_id, project_id, created_at)
ORDER BY pk.rn, d.created_at'
,_dates
) f (rn int, keyword_id int, project_id int, t int, y int, w int, m int)
JOIN keyword k USING (keyword_id);
END
$func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
WITH d(day) AS (SELECT '2014-07-07'::date) -- provide your date here
, v(dates) AS (
SELECT format('VALUES(%L::date), (%L), (%L), (%L)'
, day, day - 1, day - 7
,(day - interval '1 month')::date)
FROM d
)
SELECT k.name, f.keyword_id, f.project_id, d.day AS the_date
, f.t AS today, f.y As yesterday, f.w AS week, f.m AS month
FROM crosstab (
'SELECT rn
, pk.keyword_id
, pk.project_id
, d.created_at
, COALESCE(pr.pos, 0) AS pos
FROM (SELECT *, row_number() OVER () AS rn FROM project_keyword) pk
CROSS JOIN (
' || (SELECT dates FROM v) || '
) d(created_at)
LEFT JOIN (
SELECT keyword_id
, project_id
, created_at::date AS created_at
, min(position) AS pos
FROM project_report
GROUP BY keyword_id, project_id, created_at::date
) pr USING (keyword_id, project_id, created_at)
ORDER BY pk.rn, d.created_at'
,(SELECT dates FROM v)
) f (rn int, keyword_id int, project_id int
, t int, y int, w int, m int)
JOIN keyword k USING (keyword_id);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
23760 次 |
| 最近记录: |