ale*_*smn 4 postgresql performance pivot query-performance
我需要从 3 个表中提取数据,并以特定方式打印它。
http://sqlfiddle.com/#!15/59481/8
请参阅此问题以了解查询是如何生成的。小提琴中的版本部分工作,但我需要修改查询以产生不同的输出。
我有一个project_report
存储数据的表keyword
:
1. If a keyword has data for a particular day it will store it in `project_report`
2. A keyword might have no data to store for a particular day.
3. A keyword might store multiple rows of data for a particular day (the data is uniq)
4. A keyword might not have data for a particular day, but it might have for a different day.
Run Code Online (Sandbox Code Playgroud)
我相信要解决我的问题,DB 函数将是最好的方法,因为我希望能够指定一个日期并从project_reports
每个keyword
.
我不知道如何编写这个查询,以产生以下结果,也不知道什么会更好,有 aview
或 a db function
,我认为view
为了选择特定日期,我需要为每个关键字和每个日期生成这些输出。另一个问题是我还想在图表中使用这些结果,它将获取一个范围内的数据,为此我认为视图更好,然后调用函数 n 次。
所以如果keyword_id: 1
在project_report
:
ID: 1, keyword_id: 1, project_id: 1, position: 1, created_at: '2014-07-09'
ID: 2, keyword_id: 1, project_id: 1, position: 2, created_at: '2014-07-09'
Run Code Online (Sandbox Code Playgroud)
对于2014-07-09
我应该得到的选定日期(请参阅该位置将是最小位置而不是 [1, 2]):
keyword_id: 1, project_id: 1, position: 1, yesterday_pos: 0, last_week_pos: 0, last_month_pos:0 created_at: '2014-07-09'
Run Code Online (Sandbox Code Playgroud)
如果keyword_id: 2
在project_report
:
ID: 3, keyword_id: 2, project_id: 1, position: 3, created_at: '2014-07-09'
ID: 4, keyword_id: 2, project_id: 1, position: 4, created_at: '2014-07-08'
ID: 5, keyword_id: 2, project_id: 1, position: 5, created_at: '2014-07-08'
ID: 6, keyword_id: 2, project_id: 1, position: 4, created_at: '2014-07-03'
Run Code Online (Sandbox Code Playgroud)
对于选定的日期,2014-07-09
我应该得到:
keyword_id: 2, project_id: 1, position: 3, yesterday_pos: 4, last_week_pos: 4, last_month_pos: 0 created_at: '2014-07-09'
Run Code Online (Sandbox Code Playgroud)
如果keyword_id: 3
在project_report
:
ID: 7, keyword_id: 3, project_id: 1, position: 10, created_at: '2014-07-08'
ID: 8, keyword_id: 3, project_id: 1, position: 11, created_at: '2014-07-03'
Run Code Online (Sandbox Code Playgroud)
对于选定的日期,2014-07-09
我应该得到:
keyword_id: 3, project_id: 1, position: 0, yesterday_pos: 10, last_week_pos: 11, last_month_pos: 0 created_at: '2014-07-09'
Run Code Online (Sandbox Code Playgroud)
如果keyword_id: 4
在project_report
:
`nothing`
Run Code Online (Sandbox Code Playgroud)
对于选定的日期,2014-07-09
我应该得到:
keyword_id: 4, project_id: 1, position: 0, yesterday_pos: 0, last_week_pos: 0, last_month_pos: 0 created_at: '2014-07-09'
Run Code Online (Sandbox Code Playgroud)
我建议使用crosstab()
来自附加模块tablefunc 的全新方法。您需要为每个数据库安装一次。详细说明:
SELECT k.name, keyword_id, project_id, now()::date AS the_date
, t AS today, y As yesterday, w AS week, 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 (
VALUES
(now()::date)
, (now()::date - 1)
, (now()::date - 7)
,((now() - 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
$$
,$$
VALUES
(now()::date)
, (now()::date - 1)
, (now()::date - 7)
, ((now() - interval '1 month')::date)
$$
) ct (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)
返回:
name keyword_id project_id the_date today yesterday week month
Cheese 1 1 2014-07-11 1 1 1 0
Monitor 2 1 2014-07-11 2 2 2 0
Apple 3 1 2014-07-11 9 9 9 0
Apple1 4 1 2014-07-11 0 0 0 0
Iphone 5 1 2014-07-11 0 33 34 0
Run Code Online (Sandbox Code Playgroud)
我们需要每组一个唯一的列crosstab()
。由于您没有每个(keyword_id int, project_id)
我添加一个代理键row_number()
to project_keyword
。
JOIN
到一组您感兴趣的日期(今天、昨天等)。每个日期一行。
LEFT JOIN
以project_reports
附加每个日期的位置(如果有)。默认为 0 COALESCE
。
交叉制表以获得每个给定日期具有一个位置列的单行。
最后JOIN
到keyword
刚添加的name
。添加当前日期并rn
从结果中删除。
旁白:“名字”不是一个好名字。我会用一些描述性的东西来代替。
归档时间: |
|
查看次数: |
1379 次 |
最近记录: |