【问题标题】:Function to count if X amount amount of days as a full month如果 X 天数为一整月,则计算功能
【发布时间】:2017-10-16 15:40:56
【问题描述】:

我们为客户提供服务,每个客户都有 90 天的授权 我想创建一个将 15 天视为整月的函数。 例如,假设客户在 2017 年 10 月 17 日获得授权。这意味着 10 月不到 15 天,因此 10 月不计入授权,但必须计入 11 月、12 月和 2018 年 1 月。

;WITH CTE AS (
    select 
        d.ClientId,
        LOC
        datediff(day, l.DecisionOn, d.duedate) 'Days',
        l.DecisionOn,
        d.duedate
    from code d
        join codeloc l on d.curdocversionid = l.docversionid
        join codeaccess a on a.docversionid = d.curdocversionid
    where codeid = 69999
            and aoca in ('68','69','70','71','72','74')
),
T AS (
SELECT ClientId, LOC, COUNT(*) CNT FROM CTE
WHERE [Days] > 15
    AND AuthorizedDecisionOn > DATEADD(MONTH, (CASE WHEN DAY(GETDATE()) > 15 THEN 1 ELSE 0 END) , CAST( GETDATE() as date)) 
    AND duedate < DATEADD(MONTH,3 + (CASE WHEN DAY(GETDATE()) > 15 THEN 1 ELSE 0 END) , CAST( GETDATE() as date))
GROUP BY ClientId, LOC
)

【问题讨论】:

  • 您的查询有什么问题?你能从你的表中添加一些示例数据吗?
  • 他们希望能够查看在任何给定时间有多少当前客户获得授权,这些客户计入我们的目标
  • 使用适当的软件(MySQL、Oracle、DB2...)和版本标记数据库问题很有帮助,例如sql-server-2014。语法和功能的差异通常会影响答案。请注意,tsql 缩小了选择范围,但没有指定数据库。表模式、示例数据和预期结果非常有用。
  • 提示:GetDate() 在查询中的处理方式有点奇怪。每个 instance 在查询中都有一个常量值。例如select GetDate() as D1, GetDate() as D2 from SomeTable 可能会为两列返回两个不同的值,但它们不会因一行而异。在多个语句中使用 GetDate() 时,例如在存储过程中,可以通过获取单个值并在整个过程中使用它来避免有趣的意外,即declare @Now as DateTime = GetDate(); 并根据需要使用@Now

标签: sql tsql reporting-services


【解决方案1】:

这是一个内联表值函数 (iTvf),可以满足您的需求。 (注意:我使用 iTvf 是因为它们的性能优于标量 udf)

CREATE FUNCTION dbo.monthsBetweenMinDay
(
  @fromDate date,
  @toDate   date,
  @minDays  tinyint
)
RETURNS TABLE WITH SCHEMABINDING AS RETURN
SELECT Months = m.mb + 
    CASE WHEN DATEDIFF(day,d.fd,dateadd(month, -m.mb, d.td)) >= @minDays THEN 1 ELSE 0 END
FROM (VALUES (@fromDate, @toDate)) d(fd,td) -- from date and todate
CROSS APPLY (VALUES(
  CASE WHEN d.fd > d.td THEN NULL
       WHEN DATEPART(day, d.fd) > DATEPART(day, d.td) THEN DATEDIFF(month, d.fd, d.td)-1
       ELSE DATEDIFF(month, d.fd, d.td) END)) m(mb);

下面是函数的示例:

-- sample data
CREATE TABLE #dates (date1 date, date2 date);

INSERT #dates
SELECT dt.dt, CAST(DATEADD(day, [days].d, DATEADD(month, months.m, dt.dt)) as date)
FROM (VALUES ('20170101')) dt(dt), (VALUES (4),(15),(25)) [days](d), (VALUES(0),(1),(4)) months(m);

-- solution
SELECT * 
FROM #dates d
CROSS APPLY dbo.monthsBetweenMinDay(d.date1, d.date2, 15);

结果

date1       date2       Months
----------  ----------  -----------
2017-01-01  2017-01-05  0
2017-01-01  2017-01-16  1
2017-01-01  2017-01-26  1
2017-01-01  2017-02-05  1
2017-01-01  2017-02-16  2
2017-01-01  2017-02-26  2
2017-01-01  2017-05-05  4
2017-01-01  2017-05-16  5
2017-01-01  2017-05-26  5

【讨论】:

  • 这在尝试一个月的情况下是可以的。我想要它在一个月之间的几天。例如。 2017 年 8 月 28 日和 2017 年 10 月 16 日
  • 这在尝试一个月的情况下是可以的。我想要它在一个月之间的几天。例如。 8/28/2017 和 10/16/2017 Clientid, Year, Month, Count, countstowardstarget if (count > 15) 2, 2017, 8, 4, 0 2, 2017, 9, 30, 1 2, 2017, 10, 16、1组,按clientid、年、月。第 8 个月计数为 0 的原因是客户在 2017 年 8 月 28 日收到了服务,当时该月已经结束了 4 天。所以它不会计算在内。
猜你喜欢
  • 1970-01-01
  • 2017-10-18
  • 1970-01-01
  • 1970-01-01
  • 2014-05-12
  • 1970-01-01
  • 1970-01-01
  • 2014-05-08
  • 2022-11-03
相关资源
最近更新 更多