【问题标题】:Get columns of data with two different date range获取具有两个不同日期范围的数据列
【发布时间】:2021-08-04 02:49:13
【问题描述】:

我想获得过去 7 天和过去 14 天的平均评分。

我尝试使用 WITH AS 获取数据,但加载时间过长。还有其他更好的方法可以减少运行时间吗?

语法:

WITH last_7_days AS (
SELECT item, rating
FROM sales
WHERE ( 
    rating IS NOT NULL
    AND (entry_date  >= CAST((CAST(now() AS timestamp) + (INTERVAL '-7 day')) AS date) AND entry_date < CAST((CAST(now() AS timestamp) + (INTERVAL '1 day')) AS date))
    )
),

last_14_days AS (
SELECT item, rating
FROM sales
WHERE ( 
    rating IS NOT NULL
    AND (entry_date  >= CAST((CAST(now() AS timestamp) + (INTERVAL '-14 day')) AS date) AND entry_date < CAST((CAST(now() AS timestamp) + (INTERVAL '1 day')) AS date))
    )
)

SELECT last_7_days.item, avg(last_7_days.score) as "avg_last_7_days", avg(last_14_days.rating) as "avg_last_14_days", count(*) AS "count"
FROM last_7_days, last_14_days
WHERE last_7_days.item = last_14_days.item
GROUP BY last_7_days.item
ORDER BY "avg_last_7_days" DESC, last_7_days.item ASC

结果应该是这样的:

item|avg_last_7_days|avg_last_14_days|count|

谢谢

【问题讨论】:

  • 对 WHERE 语句进行强制转换非常低效。我会尽量避免所有这些强制转换,并事先在查询之上设置变量。你尝试过这样的事情吗?

标签: sql postgresql join


【解决方案1】:

使用条件聚合:

SELECT item, 
       AVG(rating) FILTER (WHERE entry_date >= NOW() + interval '-7 day' AND entry_date < NOW() + interval '1 day') AS avg_rating_last_seven_days,
       AVG(rating) FILTER (WHERE entry_date >= NOW() + interval '-14 day' AND entry_date < NOW() + interval '1 day') AS avg_rating_last_fourteen_days
FROM sales
 WHERE rating IS NOT NULL AND 
       (entry_date  >= NOW() + interval '-14 day' AND entry_date < NOW() + interval '1 day')
GROUP BY item;

注意:如果您只关心日期,那么也许您应该使用CURRENT_DATE 甚至NOW()::date

【讨论】:

  • 超级干净,喜欢!顺便说一句,即使您已经在条件聚合中指定了日期间隔,您还需要在 where 子句中指定日期间隔吗?
  • @AleixCC 。 . .它应该使查询更快一些。此外,它确保仅包含在过去两周内有评分的项目。
【解决方案2】:

摆脱所有演员表并直接在 CTE 上进行聚合应该会有所帮助,请尝试以下操作:

WITH last_7_days AS (
  SELECT 
    item, 
    AVG(rating) AS avg_rating_last_seven_days
  FROM 
    sales
  WHERE 
    rating IS NOT NULL AND 
    (entry_date  >= NOW() + interval '-7 day' AND entry_date < NOW() + interval '1 day')
  GROUP BY
    1 
),
last_14_days AS (
  SELECT 
    item, 
    AVG(rating) AS avg_rating_last_fourteen_days
  FROM 
    sales
  WHERE
    rating IS NOT NULL AND 
    (entry_date  >= NOW() + interval '-14 day' AND entry_date < NOW() + interval '1 day')
  GROUP BY
    1  
)
SELECT
  lsd.item,
  avg_rating_last_seven_days,
  avg_rating_last_fourteen_days
FROM
  last_7_days AS lsd
INNER JOIN
  last_14_days AS lfd ON lsd.item = lfd.item

如果它有助于提高您当前的表现,请告诉我!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    • 1970-01-01
    • 2020-07-25
    相关资源
    最近更新 更多