从视图或函数中的多个表中提取数据

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: 1project_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: 2project_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: 3project_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: 4project_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)

Erw*_*ter 5

我建议使用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 JOINproject_reports附加每个日期的位置(如果有)。默认为 0 COALESCE

  • 交叉制表以获得每个给定日期具有一个位置列的单行。

  • 最后JOINkeyword刚添加的name。添加当前日期并rn从结果中删除。

旁白:“名字”不是一个好名字。我会用一些描述性的东西来代替。