sql - 按天分组,在left join中显示没有数据和复杂查询的天数

标签 sql database postgresql join group-by

我在 PostgreSQL 9.4.4 中有复杂的 SQL 查询:

SELECT
  p.id,
  p.name,
  p.page_variant_id,
  p.variant_name,
  (
    SELECT COUNT(*) FROM page_views
    INNER JOIN unique_page_visits upv ON upv.id = page_views.unique_page_visit_id
    WHERE page_views.page_id = p.id AND upv.updated_at >= '2015-08-15' AND
          upv.updated_at <= '2015-08-22'
  ) as views_count,
  (
    SELECT COUNT(*) FROM unique_page_visits upv
    WHERE upv.page_id = p.id  AND upv.updated_at >= '2015-08-15' AND
          upv.updated_at <= '2015-08-22'
  ) as page_visits_count,
  (
    SELECT COUNT(*) FROM conversions
    INNER JOIN conversion_goals cg ON cg.id = conversions.conversion_goal_id
    INNER JOIN unique_page_visits upv ON upv.id = conversions.unique_page_visit_id
    WHERE cg.page_id = p.id  AND conversions.updated_at >= '2015-08-15' AND
          conversions.updated_at <= '2015-08-22' AND cg.name = 'popup'
  ) as conversions_count
FROM
  pages p
WHERE
  p.page_variant_id = '25'
ORDER BY
  p.id ASC

示例结果:

 id | name | page_variant_id | variant_name | views_count | page_visits_count | conversions_count 
----+------+-----------------+--------------+-------------+-------------------+-------------------
 73 | a    |              25 | Original     |           1 |                 1 |                 1
(1 row)

我不知道这个查询是否以最好的方式编写,但它有效。
欢迎任何改进! - 删除 SELECT 子查询中的冗余,例如:

AND upv.updated_at >= '2015-08-15' AND upv.updated_at <= '2015-08-22'

问题 是我必须按天对结果进行分组。每一天都必须出现在结果中,即使那天没有找到任何行。

我可以重复使用 this code (我稍微修改了一下;归功于 Erwin Brandstetter):

SELECT *
FROM  (SELECT generate_series('2015-08-15'::date
                            , '2015-08-22'::date
                            , '1 day'::interval)::date) AS d(day)
LEFT   JOIN (
   SELECT date_trunc('month', date_col)::date AS day
        , count(*) AS some_count
   FROM   tbl
   WHERE  date_col >= '2007-12-01'::date
   AND    date_col <= '2008-12-06'::date
-- AND    ... more conditions
   GROUP  BY 1
   ) t USING (day)
ORDER  BY 1;

主要问题是我需要在created_at字段上LEFT JOIN(转换为date ) 到表 page_viewsconversionsunique_page_visits,而不是 pages 表(主查询,不是子查询-在SELECT区域查询)。

伪代码:

SELECT * 
FROM
    (SELECT generate_series('2015-08-15'::date
                          , '2015-08-22'::date
                          , '1 day'::interval)::date) AS d(day)

LEFT JOIN (
  SELECT day_from_subquery_not_from_pages::data AS day
  -- other stuff to return proper results AND conditions
) t USING(day)   

这可能吗?

或者我可能不得不将这个大型查询拆分为子查询(然后我将有 3 个...),然后使用 UNION 连接结果?然后我可以从子查询中 JOIN ON days ...

实现此目标的最佳方法是什么?

最佳答案

猜测缺少的详细信息,此查询可能是您要查找的内容:

WITH p AS (
   SELECT '2015-08-15'::date AS a, '2015-08-22'::date AS z  -- enter bounds once
        , id, name, page_variant_id, variant_name
   FROM   pages
   WHERE  page_variant_id = '25'   -- enter ID once
   )
SELECT p.id, p.name, p.page_variant_id, p.variant_name
     , day, v.views_count, pv.page_visits_count, c.conversions_count
FROM   p
     , LATERAL (SELECT day::date FROM generate_series(p.a, p.z, interval '1 day') day) d
LEFT   JOIN (
   SELECT upv.updated_at::date AS day, count(*) AS views_count
   FROM                      p
   JOIN   page_views         pv  ON pv.page_id = p.id
   JOIN   unique_page_visits upv ON upv.id = pv.unique_page_visit_id
   WHERE  upv.updated_at BETWEEN p.a AND p.z
   GROUP  BY 1
   ) v USING (day)
LEFT JOIN (
   SELECT upv.updated_at::date AS day, count(*) AS page_visits_count
   FROM                      p
   JOIN   unique_page_visits upv ON upv.page_id = p.id
   WHERE  upv.updated_at BETWEEN p.a AND p.z
   GROUP  BY 1
   ) pv USING (day)
LEFT JOIN (
   SELECT upv.updated_at::date AS day, count(*) AS conversions_count
   FROM                      p
   JOIN   conversion_goals   cg  ON cg.page_id = p.id
   JOIN   conversions        c   ON c.conversion_goal_id = cg.id
   JOIN   unique_page_visits upv ON upv.id = c.unique_page_visit_id
   WHERE  cg.name = 'popup'
   AND    c.updated_at BETWEEN p.a AND p.z
   GROUP  BY 1
   ) c USING (day)
ORDER  BY day;

关于sql - 按天分组,在left join中显示没有数据和复杂查询的天数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32129872/

相关文章:

javascript - 将 Javascript 对象保存到 NoSQL 数据库中并在之后检索它

sql - 具有窗口函数滞后的 Postgres 组结果返回 0 行

sql - 从 Oracle SQL*Plus 中执行函数时行为不一致?

sql - 将多个选择和更新子句截断为一个子句

MySQL 连接两个表的帮助

php - 每行返回多行(在 Zend Framework 中)

sql - 计算其他表中的值

Php 找不到 PostgreSQL 库,尽管它存在于指定的文件夹中

sql - SSIS - 将 nchar 空字符串转换为 int 时出现表达式计算错误

java - 如何在MySQL中使用表达式作为OFFSET?