更新时间:2023-01-30 10:58:43
我从头开始研究了一些东西,似乎可以满足您的所有需求,
I worked out something from scratch, and it seems to cover all your needs, though you can update us back if something's missing.
考虑到这是一个全新的起点,并且从不同的角度出发,您可能会发现其中的某些技术或想法。另外,对我来说似乎更简单,但这也许是因为我正在审阅自己的作品...
Considering it's a fresh start and coming from a different angle, you might discover certain techniques or ideas out of it. Also, it does seem simpler to me but maybe that's because I'm reviewing my own work...
最后一点,我将依靠一种技巧之前阅读过,以逐行方式应用 MIN
和 MAX
,抽象示例:
One last note, I'll be relying on a trick I read before, that applies MIN
and MAX
in a row-wise fashion, abstract example:
SELECT MAX([value]) AS [MAX], MIN([value]) AS [MIN]
FROM (
VALUES (CURRENT_TIMESTAMP), (@Start_Date), (@End_Date), (NULL), (0)
) AS [data]([value])
首先,想一想开始和结束时间的长短。结束日期:
First off, thought of figuring the amount of time outside start & end days:
SELECT MinutesExcludingStartAndEndDays = MAX([value])
FROM (VALUES (0), ((DATEDIFF(DAY, @Start_Date, @End_Date) - 1) * 840)) AS [data]([value])
第二步,计算开始时间相对于晚上8点的时间(如果两天都匹配,则为或结束时间):
Second, figuring the time during starting day, against 8pm (or end time if both days match):
SELECT MinutesOnStartDay = DATEDIFF(MINUTE, @Start_Date, MIN([value]))
FROM (VALUES (@End_Date), (DATETIMEFROMPARTS(YEAR(@Start_Date), MONTH(@Start_Date), DAY(@Start_Date), 20, 0, 0, 0))) AS [data]([value])
第三与第二非常相似,但是请注意,如果开始日期和结束日期相同,则我们不应同时计算第二和第三天。我决定在第三行中使用 CASE
语句来处理该问题:
Third is very similar to second, however note that if start and end days were the same, we should not count both second and third. I decided to handle that with a CASE
statement within third:
SELECT MinutesOnEndDayIfNotStartDay = CASE DATEDIFF(DAY, @Start_Date, @End_Date) WHEN 0 THEN 0 ELSE DATEDIFF(MINUTE, MAX([value]), @End_Date) END
FROM (VALUES (@Start_Date), (DATETIMEFROMPARTS(YEAR(@End_Date), MONTH(@End_Date), DAY(@End_Date), 6, 0, 0, 0))) AS [data]([value])
第四,如果开始日期或结束日期是在周末,则应将其从那里移开:
Fourth, if either start or end dates land on a weekend, it should be pushed away from there:
DECLARE @Mod int
SET @Mod = CONVERT(int, @Start_Date) % 7
IF @Mod IN (5, 6)
SET @Start_Date = DATEADD(DAY, CASE @Mod WHEN 5 THEN 2 WHEN 6 THEN 1 ELSE 0/0 END, DATETIMEFROMPARTS(YEAR(@Start_Date), MONTH(@Start_Date), DAY(@Start_Date), 6, 0, 0, 0))
SET @Mod = CONVERT(int, @End_Date) % 7
IF @Mod IN (5, 6)
SET @End_Date = DATEADD(DAY, CASE @Mod WHEN 5 THEN -1 WHEN 6 THEN -2 ELSE 0/0 END, DATETIMEFROMPARTS(YEAR(@End_Date), MONTH(@End_Date), DAY(@End_Date), 20, 0, 0, 0))
最后,在目标时期内完全包含周末的问题,为此请查看这个问题,从选票中我只能猜到他们已经解决了。
Lastly, the issue of having weekend days fully encompassed within your target period, for that have a look at this question, from the votes there I can only guess they worked it out already.