动态日期 SQL 服务器
Dynamic Dates SQL Server
我在 SQL 中有以下数据。
我需要想出一种方法来根据下面的 2 个值动态获取下一个日期。剩余剂量告诉我需要查找多少日期,RXDAYS 告诉我查找日期的增量
Date Shipped Remaining Doses RXDAYS
2019-06-05 2 30
所以根据上面的内容,我会找到 2019-06-05 后 30 天的日期,得到 2019-07-05,再过 30 天,我会得到 2019-08-04。
有办法吗?
使用dateadd()
。这为您提供了最终日期:
dateadd(day, doses * rxdays, date_shipped)
另一方面,如果您想生成新行,则可以使用递归查询:
with cte as (
select date_shipped mydate, doses, rxdays from mytable
union all
select (dateadd(day, rxdays, date_shipped), doses - 1, rxdays
from cte
where doses > 0
)
select mydate from cte
对于您问题中显示的示例数据行,这将生成三行,日期为 2019-06-05
、2019-07-05
和 2019-08-04
。
如果 doses
的值大于 100
,那么您需要在查询的最后添加 option(maxrecursion 0)
。
您可以使用DATEADD()
函数作为
SELECT *, CONVERT(DATE, DATEADD(Day, RXDAYS, DateShipped)) FirstDateToFind,
CONVERT(DATE, DATEADD(Day, RXDAYS * 2, DateShipped)) SecondDateToFind
FROM
(
VALUES
('2019-06-05', 2, 30)
) T(DateShipped, RemainingDoses, RXDAYS);
更新:
您似乎正在寻找生成如下行的行:
WITH Data AS
(
SELECT *
FROM T
UNION ALL
SELECT CONVERT(DATE, DATEADD(Day, (RXDAYS * (RemainingDoses - RemainingDoses + 1)), DateShipped)),
RemainingDoses - 1,
RXDAYS
FROM Data
WHERE RemainingDoses > 0
)
SELECT *
FROM Data
ORDER BY DateShipped;
这是一个db<>fiddle
另一种方法是使用数字 table(如果您还没有数字,也可以即时创建自己的数字)。假设您不能提供超过 255 剂:
DECLARE @Doses table
(
RowID int IDENTITY(1,1),
DateShipped date,
RemainingDoses tinyint,
RXDays tinyint
);
INSERT @Doses(DateShipped, RemainingDoses, RXDays)
VALUES('20190605',2,30),('20190704',3,24);
-- pseudo Numbers table
DECLARE @num table(n tinyint);
INSERT @num(n) SELECT TOP (256)
row_number() OVER (ORDER BY (SELECT NULL)) - 1
FROM sys.all_columns;
SELECT d.RowID, d.DateShipped, d.RemainingDoses, d.RXDays,
SubsequentShipdate = DATEADD(DAY, n.n*d.RXDays, d.DateShipped)
FROM @Doses AS d
INNER JOIN @num AS n
ON n.n <= d.RemainingDoses
ORDER BY d.RowID, SubsequentShipdate;
结果:
如果您只想要 "next" 日期而不包括原始行,只需添加:
AND n.n > 0
或者,不要在数字 table 中包含 0
(尽管它 可以 有用):
INSERT @num(n) SELECT TOP (255)
row_number() OVER (ORDER BY (SELECT NULL))
我在 SQL 中有以下数据。
我需要想出一种方法来根据下面的 2 个值动态获取下一个日期。剩余剂量告诉我需要查找多少日期,RXDAYS 告诉我查找日期的增量
Date Shipped Remaining Doses RXDAYS
2019-06-05 2 30
所以根据上面的内容,我会找到 2019-06-05 后 30 天的日期,得到 2019-07-05,再过 30 天,我会得到 2019-08-04。
有办法吗?
使用dateadd()
。这为您提供了最终日期:
dateadd(day, doses * rxdays, date_shipped)
另一方面,如果您想生成新行,则可以使用递归查询:
with cte as (
select date_shipped mydate, doses, rxdays from mytable
union all
select (dateadd(day, rxdays, date_shipped), doses - 1, rxdays
from cte
where doses > 0
)
select mydate from cte
对于您问题中显示的示例数据行,这将生成三行,日期为 2019-06-05
、2019-07-05
和 2019-08-04
。
如果 doses
的值大于 100
,那么您需要在查询的最后添加 option(maxrecursion 0)
。
您可以使用DATEADD()
函数作为
SELECT *, CONVERT(DATE, DATEADD(Day, RXDAYS, DateShipped)) FirstDateToFind,
CONVERT(DATE, DATEADD(Day, RXDAYS * 2, DateShipped)) SecondDateToFind
FROM
(
VALUES
('2019-06-05', 2, 30)
) T(DateShipped, RemainingDoses, RXDAYS);
更新:
您似乎正在寻找生成如下行的行:
WITH Data AS
(
SELECT *
FROM T
UNION ALL
SELECT CONVERT(DATE, DATEADD(Day, (RXDAYS * (RemainingDoses - RemainingDoses + 1)), DateShipped)),
RemainingDoses - 1,
RXDAYS
FROM Data
WHERE RemainingDoses > 0
)
SELECT *
FROM Data
ORDER BY DateShipped;
这是一个db<>fiddle
另一种方法是使用数字 table(如果您还没有数字,也可以即时创建自己的数字)。假设您不能提供超过 255 剂:
DECLARE @Doses table
(
RowID int IDENTITY(1,1),
DateShipped date,
RemainingDoses tinyint,
RXDays tinyint
);
INSERT @Doses(DateShipped, RemainingDoses, RXDays)
VALUES('20190605',2,30),('20190704',3,24);
-- pseudo Numbers table
DECLARE @num table(n tinyint);
INSERT @num(n) SELECT TOP (256)
row_number() OVER (ORDER BY (SELECT NULL)) - 1
FROM sys.all_columns;
SELECT d.RowID, d.DateShipped, d.RemainingDoses, d.RXDays,
SubsequentShipdate = DATEADD(DAY, n.n*d.RXDays, d.DateShipped)
FROM @Doses AS d
INNER JOIN @num AS n
ON n.n <= d.RemainingDoses
ORDER BY d.RowID, SubsequentShipdate;
结果:
如果您只想要 "next" 日期而不包括原始行,只需添加:
AND n.n > 0
或者,不要在数字 table 中包含 0
(尽管它 可以 有用):
INSERT @num(n) SELECT TOP (255)
row_number() OVER (ORDER BY (SELECT NULL))