按任意开始和结束日期对订单表进行分区
Posted
技术标签:
【中文标题】按任意开始和结束日期对订单表进行分区【英文标题】:Partition Orders table by arbitrary start and end day-of-month 【发布时间】:2020-08-12 05:25:14 【问题描述】:鉴于以下相当标准的订单表:
CREATE TABLE [dbo].[orders](
[bill_product_id] [int] IDENTITY(1,1) NOT NULL,
[Bill_date] [datetime] NULL,
[TenantId] [int] NULL,
[Product_type] [int] NULL,
[Quantity] [int] NULL,
[Customer_cost] [numeric](18, 10)
)
以下查询为我提供表orders
中有记录的每个月的开始日期和结束日期
SELECT distinct DATEADD(DAY,1,EOMONTH(bill_date,-1)) as start_date,
EOMONTH(bill_date) as end_date
FROM orders
示例结果集:
开始日期结束日期
2020-07-01 2020-07-31
2020-08-01 2020-08-31
现在我们需要更改“结算周期”,因此我们需要从每月 26 日开始结算周期,而不是从每月 1 日开始,到每月最后一天结束,月底是下个月的第 25 天(不要问)。
我确定我可以根据开始日期确定 end_date,但我不确定将数据划分为月份的 26 日至 25 日的最佳方式。请提出一个有效的方法来做到这一点。
【问题讨论】:
【参考方案1】:也许你可以使用DATEFROMPARTS
DECLARE @bill_date DATE = '2020-08-12'
SELECT DATEFROMPARTS(YEAR(@bill_date), MONTH(@bill_date), 26)
,DATEFROMPARTS(YEAR(@bill_date), MONTH(@bill_date) + 1, 25)
但你的方式也是有效的,可以加强。
正如你所指出的,它应该是:
SELECT DATEFROMPARTS(YEAR(@bill_date), MONTH(@bill_date) - (CASE WHEN DAY(@bill_date) >= 26 then 0 else 1 end) , 26);
为了确保小于26
的日期保持在当前间隔内,而不是像我原来的解决方案中那样的下一个。
【讨论】:
这给出了从 8 月 26 日开始的 next 间隔。我尝试从两个“月份”部分中减去 1,但如果给出的日期是“2020-”,这将不起作用07-30' - 计算到 6 月 26 日,应该是 7 月 26 日 对于2020-07-30
,我得到2020-07-26
和2020-08-25
。这不是你需要的吗?
是的,但如果给定 '2020-08-12',相同的函数会返回未来的日期 - 而不是当前的时间间隔。但是 DATEFROMPARTS 帮我找到了真正的解决方案: SELECT DATEFROMPARTS(YEAR(@bill_date), MONTH(@bill_date) - (CASE WHEN DAY(@bill_date) >= 26 then 0 else 1 end) , 26);
@Black 我现在明白逻辑了 :-)【参考方案2】:
感谢@gotqn,我可以按如下方式使用 DATEFROMPARTS
SELECT DATEFROMPARTS(YEAR(@bill_date),
MONTH(@bill_date) - (CASE WHEN DAY(@bill_date) >= 26 then 0 else 1 end),
26) as start_date
,DATEFROMPARTS(YEAR(@bill_date),
MONTH(@bill_date) + (CASE WHEN DAY(@bill_date) >= 26 then 1 else 0 end),
25) as end_date
【讨论】:
【参考方案3】:您可以减去 26 天并使用 datefromparts()
:
SELECT DISTINCT DATEFROMPARTS(YEAR(yyyymm_start), MONTH(yyyymm_start), 26) as start_date,
DATEFROMPARTS(YEAR(yyyymm_end), MONTH(yyymm_end), 25) as end_date
FROM orders o CROSS APPLY
(VALUES (DATEADD(DAY, -26, BILL_DATE),
DATEADD(MONTH, 1, DATEADD(DAY, -26, BILL_DATE))
)
) as v(yyyymm_start, yyyymm_end)
【讨论】:
【参考方案4】:只需使用 dateadd 即可“移动”您的计费周期。
我假设然后你查询
declare @billDate date = '2020-07-16'
SELECT distinct DATEADD(DAY,1,EOMONTH(@billDate)) as start_date,
EOMONTH(@billDate) as end_date, 'Original' as query
--FROM orders
SELECT distinct DATEADD(DAY,26,EOMONTH(@billDate,-1)) as start_date,
dateadd(day,25,EOMONTH(@billDate) )as end_date, 'Modified' as query
--FROM orders
会导致
start_date end_date query
---------- ---------- --------
2020-07-01 2020-07-31 Original
start_date end_date query
---------- ---------- --------
2020-07-26 2020-08-25 Modified
【讨论】:
这与@gotqn 的原始答案有相同的问题,即对于 '2020-08-10' 它返回 future 间隔 2020-08-26 到 2020-09- 25 已修复,在 eomonth 函数中添加了 -1 没有。现在它返回值“2020-07-30”的错误(先前)间隔 请张贴给定账单日期的预计开始/结束日期 这一切都在原始帖子中,也在@gotqn 的答案中。不用担心,它已经被正确回答了以上是关于按任意开始和结束日期对订单表进行分区的主要内容,如果未能解决你的问题,请参考以下文章