【问题标题】:Apply window function logic on an interval在间隔上应用窗口函数逻辑
【发布时间】:2016-04-06 20:57:43
【问题描述】:

我有下表:

 +----------+----------+--------------+
| Customer |  Month   | Had Meeting? |
+----------+----------+--------------+
| John     | Jan-15   | N            |
| John     | Feb-15   | Y            |
| John     | March-15 | Y            |
| John     | April-15 | N            |
| John     | May-15   | N            |
| John     | June-15  | N            |
| John     | July-15  | N            |
| John     | Aug-15   | N            |
| John     | Sep-15   | N            |
| John     | Oct-15   | N            |
| John     | Nov-15   | Y            |
| John     | Dec-15   | N            |
+----------+----------+--------------+
  1. 我希望应用一个逻辑来查看客户并检查他在滚动的 3 个月期间是否有任何会议。这一时期是指会议可能发生的动态间隔。即 - 在 5 月 15 日的记录中,我希望查看 2 月至 7 月之间的时期。

  2. 如果有超过 1 个会议,我希望返回最早的会议。

即,在 1 月 15 日,我想查看 1 月和 3 月之间的间隔,它捕获了 2 次会议,我想返回两者中较早的一次(2 月)。

2 月我想查看 1 月和 4 月之间的时间间隔(前 2 个月和后 2 个月)-再次,它应该返回 2 月的会议。

3 月我希望查看 1 月 - 5 月(这实际上是我需要捕获的 2 个月之前和 2 个月之后的完整时间迭代) - 再次返回 2 月。

我希望从这个数据集中获得的最终结果是 2 月和 11 月的会议。 我想我需要类似的东西:

row_number() over(partition by Customer order by Sale_made, Month Rows between 2 preceding and 2 following)

但是 row_number 不能用作窗口函数。

我使用的是 TD v 13.0。

感谢您的帮助。

阿萨夫。

【问题讨论】:

  • 为什么03.03.201510.11.2015 应该出现在您的结果中?它们不符合 3 个月的间隔,即使符合,您的逻辑中的第 3 点在这种情况下似乎也不清楚。
  • 我的意图是在滚动的 3 个月间隔内仅捕获一次会议。在上面的例子中,1 月到 3 月之间有 2 次会议,因此我只收到销售会议的结果。
  • 请编辑您的问题,提供有关您的间隔的信息。您是否在 WHERE 条件下根据当前日期查询间隔?如果在当前窗口(3 个月)内没有会议结束销售,那么应该返回哪个日期?当前窗口的最小值?如果在这 3 个月内所有会议结束日期都是 null 怎么办?你需要澄清一些事情。现在一切都guess'n'go
  • 感谢您的评论。我简化了问题并改变了问题的范围。
  • 你试过COUNT(CASE WHEN had_meeting = 'y' THEN 1 ELSE 0 END) over(partition by Customer order by Sale_made, Month Rows between 2 preceding and 2 following)

标签: sql teradata


【解决方案1】:

如果有一个会议,您似乎想要返回一行,而 Had Meeting? 的上一行是至少三个月前。

SELECT *
FROM tab
WHERE "Had Meeting?" = 'Y' -- no need for rows without meeting
QUALIFY 
   COALESCE(MAX("Month") -- previous row's date (i.e. LAG syntax)
            OVER (PARTITION BY Customer 
                  ORDER BY "Month"
                  ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING)
            ,DATE '0001-01-01') -- otherwise 1st row will return NULL
   < ADD_MONTHS("Month", -3)  -- three month before the current row's date

【讨论】:

    【解决方案2】:

    试一试,我必须转换日期,所以现在它们是 varchar

    create table #table(
    Customer varchar(50),
    [Month] varchar(50),
    [Had Meeting] varchar(1)
    )
    
    INSERT INTO #table (Customer, [Month], [Had Meeting])
      VALUES 
      ('John', 'Jan-15', 'N'),
      ('John', 'Feb-15', 'Y'),
      ('John', 'March-15', 'Y'),
      ('John', 'April-15', 'N'),
      ('John', 'May-15', 'N'),
      ('John', 'June-15 ', 'N'),
      ('John', 'July-15 ', 'N'),
      ('John', ' Aug-15', 'N'),
      ('John', ' Sep-15', 'N'),
      ('John', ' Oct-15', 'N'),
      ('John', 'Nov-15', 'Y'),
      ('John', 'Dec-15', 'N')
    
    DECLARE @searchdate datetime = '2015-05-01 00:00:00.000'
    
    SELECT TOP 1
      Customer,
      MIN([Month]) AS [Month],
      [Had Meeting]
    FROM #table
    WHERE DATEPART(YEAR, @searchdate) = DATEPART(YEAR, DATEADD(YEAR, -1, GETDATE()))
    AND [Had Meeting] = 'Y'
    AND CONVERT(datetime, '1-' + [Month], 104) >= DATEADD(MONTH, -2, @searchdate)
    AND DATEPART(MONTH, CONVERT(datetime, '1-' + [Month], 104)) <= (DATEPART(MONTH, @searchdate) + 2)
    AND Customer = 'John'
    GROUP BY Customer,
             [Month],
             [Had Meeting]

    【讨论】:

    • 嗨,Kurt,谢谢,但这不是 TD 代码。此外,我正在寻找一种更简单的解决方案(如果有的话)而不声明变量。
    • @AsafLahav 我只使用了一个变量来简化示例,可以将其替换为您的日期。
    猜你喜欢
    • 1970-01-01
    • 2017-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    相关资源
    最近更新 更多