【发布时间】:2015-11-14 18:45:55
【问题描述】:
我在 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_views、conversions 和unique_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 ONdays ...
实现这一目标的最佳方法是什么?
【问题讨论】:
-
在您提醒后我清理了我的referenced answer。最好将
generate_series()等返回集合的函数移到FROM列表中。 -
和往常一样,底层表的定义是必不可少的。确切的数据类型和约束与设计最佳查询相关。您可以在 sql fiddle (random example from today) 中提供一个测试用例。
标签: sql database postgresql join group-by