【问题标题】:How to get six weeks data from a week column?如何从一周列中获取六周数据?
【发布时间】:2021-04-17 19:51:29
【问题描述】:

我有一个旧查询,我正在其中查找六周的数据,如下所示。在我的以下 AND 条件下,我获得了过去六周的数据,并且在 2020 中间和结束时运行良好。但自从2021 开始后,由于我正在用 6 做明显的减法,这停止了工作。

AND data.week_col::integer BETWEEN DATE_PART(w, CURRENT_DATE) - 6 AND DATE_PART(w, CURRENT_DATE) - 1

上述查询中有一个错误,因此它在 2021 年停止工作。如何更改上述条件,以便它可以全年正常工作,并提供过去 6 周的数据。

更新

以下是我正在运行的查询:

select *,
dateadd(d, - datepart(dow, trunc(CONVERT_TIMEZONE('UTC','PST8PDT',client_date))), trunc(CONVERT_TIMEZONE('UTC','PST8PDT',client_date)) + 6) as day,
date_part(week, day) as week_col
from holder data
where data.week_col::integer BETWEEN DATE_PART(w, CURRENT_DATE) - 6 AND DATE_PART(w, CURRENT_DATE) - 1

client_date 列具有这样的值 - 2021-01-15 21:30:00.0。从那里我得到day 列的值,从day 列我得到值 week_col列如上图。

week_col 列的值类似于 5352 ...。通常是周数。

由于我的AND 条件,我只获取1 周的数据,但从技术上讲,我想要49505152531 的数据为六个星期过去了。我可以在这里使用day 列来纠正过去六周的情况吗?

【问题讨论】:

  • 编辑您的问题并显示示例数据和所需结果。目前尚不清楚data.week 长什么样。
  • 我们没有完整的图片来帮助您进行查询。如果您唯一的列是周,则该任务是不可能的。它不再起作用的原因是今年我们在第 3 周,而您基本上是在 -3 和 2 之间选择周。向我们展示了更多您的代码、表结构等。
  • 好的,我现在用我的查询和一些额外列的详细信息更新了它。
  • 您的数据库中有 calendar'esqe 表吗?意思是一个表,其中包含一组逻辑上的连续日期,以及可能的周数值。
  • @RossBush 很遗憾,我们没有。

标签: sql amazon-web-services amazon-redshift


【解决方案1】:

这可以作为解决方案吗?我对 redshirt 语法了解不多,但我读到它支持 dateadd()。如果您将 client_date 标准化为没有时间的时区转换日期,那么为什么不简单地使用它来与转换为同一时区的当前日期进行比较。

WHERE
    client_date BETWEEN
    DATEADD(WEEK,-6,trunc(CONVERT_TIMEZONE('UTC','PST8PDT',CURRENT_DATE)))
    AND
    DATEADD(WEEK,-1,trunc(CONVERT_TIMEZONE('UTC','PST8PDT',CURRENT_DATE)))

如果上述逻辑可行,那么您可能需要将 -6 和 -1 周转换为变量(如果支持)。

解决方案 2

这有点冗长,但涉及虚拟化日历表,然后将您当前的日期参数加入日历数据中,用于标记。最后,您可以将您的数据与按时间顺序按周标准化的日历结合起来。

这是 SQL Server 语法,不过,我确信它可以转换为 RS。

DECLARE @D TABLE(client_date DATETIME)
INSERT @D VALUES
('11/20/2020'),('11/27/2020'),
('12/4/2020'),('12/11/2020'),('12/18/2020'),('12/25/2020'),
('01/8/2021'),('01/8/2021'),('1/15/2021'),('1/22/2021'),('1/29/2021')

DECLARE @Date DATETIME = '1/23/2021'
DECLARE @StartDate DATETIME = '01/01/2010'
DECLARE @NumberOfDays INT = 6000

;WITH R1(N) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    R2(N) AS (SELECT 1 FROM R1 a, R1 b),
    R3(N) AS (SELECT 1 FROM R2 a, R2 b), 
    Tally(Number) AS (SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM R3)
    
,WithTally AS   
(
    SELECT CalendarDate = DATEADD(DAY,T.Number,@StartDate)
    FROM Tally T
    WHERE T.Number < @NumberOfDays
)   
,Calendar AS
(
    SELECT
        CalendarDate,
        WeekIndex = DENSE_RANK() OVER(ORDER BY  DATEPART(YEAR, CalendarDate), DATEPART(WEEK, CalendarDate))
    FROM
        WithTally                   
),
CalendarAlignedWithCurrentDateParamater AS
(
    SELECT *
    FROM
        Calendar
        CROSS JOIN (SELECT WeekIndexForToday=WeekIndex FROM Calendar WHERE Calendar.CalendarDate=@Date  ) AS X
)
SELECT 
    D.*,
    C.WeekIndex,
    C.WeekIndexForToday
FROM 
    CalendarAlignedWithCurrentDateParamater C
    INNER JOIN @D D ON D.client_date = C.CalendarDate
WHERE 
    C.WeekIndex BETWEEN C.WeekIndexForToday-6 AND C.WeekIndexForToday-1 
    
OPTION (MAXRECURSION 0) 

【讨论】:

  • 我尝试了你的建议,但与在同一查询中这样的硬编码周相比,它给我的行数更少 where data.week_in ('49', '50', '51', '52', '53', '1'). Any thoughts why it could be?
  • 可能是 DATEADD() 没有落在一周的边界上。我发布的第二个解决方案使用实际的周数倒数。这样你就想在“几周之间”跌倒
  • Redshift 没有声明变量的概念,所以恐怕这对我不起作用。链接here
  • 好吧,你可以硬编码这些值。创建临时日期表只是一个概念。如果您要运行大量基于日期的报告和/或处理,那么您可以从日历表中受益。只需定义一系列适合您的业务需求的连续日期,然后使用与日期相关的任何内容填充它,例如 DayOfWeek、WeekOfYear、MonthOfYear、IsWeekend、IsHoliday、QuarterOfYear 等。它将使这些类型的查询变得如此之多更容易使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多