1

我正在为我们公司正在做的笔记本电脑更新编写一个预订系统。我需要能够计算哪些日子有可用的插槽并将它们返回以在日历控件上呈现(即,如果一天有可用的日子它是可选的,否则不是。

逻辑如下:

  • 技术人员每天可以制造 3 台笔记本电脑。
  • 任何一天都可能有 1、2 或 3 名技术人员可用。
  • 一张桌子将保存已经进行的预订

每天可用槽的总数是(伪代码):

((laptops per day) * (technicians available)) - slots already booked

我的问题是,得出这个的最有效方法是什么?我想它最好在 SQL 端完成,它有一个函数来返回一个带有可用插槽的日期表。(不管有多少,只要至少有一个插槽可用。)

到目前为止,我可以理解所有这些。我坚持的一点是,我不想拥有所有可能日期的表格,因为它似乎效率低下。我想要做的是有效地迭代从现在到未来 3 个月之间的一系列日期,并从那里计算可用日期。

我可以在 c# 中执行此操作,但它让我觉得效率低下,因为它必须每天都在访问 SQL 服务器。在 SQL 方面似乎更好,但我不知道如何以这种方式迭代可能的日期。

到目前为止的解决方案

使用@Chris 的方法,我可以获得插槽书不超过设定最大值的日期范围:

DECLARE @startDate DATE
DECLARE @endDate DATE

SET @startDate = GETDATE()
SET @endDate = DATEADD(m,3,@startDate)
;
WITH dates(Date) AS 
(
    SELECT @startdate as Date
    UNION ALL
    SELECT DATEADD(d,1,[Date])
    FROM dates 
    WHERE DATE < @enddate
)

SELECT Date
FROM dates 
EXCEPT
SELECT date
        FROM tl_sb_booking
        GROUP BY date
        HAVING COUNT(date) < 3

这只是设置任意最多 3 个预订。下一步是添加技术人员可用性!

4

3 回答 3

2

这个答案解决了问题的一部分:“我希望能够有效地迭代从现在到未来 3 个月之间的日期范围,并从那里计算可用日期。”

如果您使用的是 MSSQL,那么 CTE 可能会有所帮助。要动态生成您的日期范围代码,可以使用如下所示:

DECLARE @startDate DATE
DECLARE @endDate DATE

SET @startDate = GETDATE()
SET @endDate = DATEADD(m,3,@startDate)
;
WITH dates(Date) AS 
(
    SELECT @startdate as Date
    UNION ALL
    SELECT DATEADD(d,1,[Date])
    FROM dates 
    WHERE DATE < @enddate
)

SELECT Date
FROM dates

然后,最后一个 SELECT 可以加入您的其他表以获取该日期的数据,进行计算等。

但是,这不一定是最好的方法。假设您有某种方法可以获取每天有多少工程师空闲的列表,则无需遍历任何其他日期(因为您知道这些日期将没有空位)。所以为此目的是这样的:

SELECT count(1), Date
From EngineerWorkDays
GROUP BY Date
Where Date>= Getdate()
and Date < DATEADD(m,3,Getdate())

将返回有可能完成工作的日期列表。另一个选择来获得已分配的工作将为您提供所需的所有数据。然后,在 c# 中的显示代码中,您可以每天迭代并检查您的数据集是否有任何相关数据(工程师是否可用、有多少、已经预订了多少工作等)。

并且不要忘记这是否是一个共享应用程序,用于在预订之前检查某个日期是否还有空间,以防其他人在您进行初始查询后预订了一些东西。

于 2013-06-19T18:23:41.383 回答
1

尝试这个:

Select [DatesAvailable] From TableName
Where [DatesAvailable] Between BeginningDate And DateAdd(m, 3, BeginningDate) And
      SlotsAvailable > 0

这应该为您提供在接下来的 3 个月内有空位的任何日期......

于 2013-06-19T18:12:30.300 回答
0

这是一种方法:

DECLARE @iToday As INT; SET @iToday = CAST(GetDate() As INT);
DECLARE @iDays As INT;  SET @iDays = 90;

WITH cte_0to9 As
(
    Select 0 As Num UNION ALL Select 1 UNION ALL Select 2 UNION ALL Select 3
    UNION ALL Select 4 UNION ALL Select 5 UNION ALL Select 6 UNION ALL Select 7
    UNION ALL Select 8  UNION ALL Select 9
)
, cte_0to99 As
(
    SELECT  (Tens.Num * 10) + Ones.Num As Num
    FROM        cte_0to9 As Ones
    CROSS JOIN  cte_0to9 As Tens
)
, cteDays As 
(
    SELECT  CAST(@iToday + Num As DATETIME) As PossibleDate
    FROM    cte_0to99
    WHERE   Num <= @iDays
)
, cteTechnicianUtilization As
(
    SELECT  t.Technician,
            d.PossibleDate,
            (Select COUNT(*) From Bookings b
             Where b.Technician = t.Technician
               And b.BookDate = d.PossibleDate) As SlotsUsed
    FROM    Technicians As t
    CROSS JOIN cteDays d
)
SELECT  PossibleDate, SUM(Util-3) As TotalAvailableSlots
FROM    cteTechnicianUtilization
WHERE   Util < 3
GROUP BY PossibleDate
HAVING  SUM(Util-3) > 0

请注意,这种方法虽然更长(代码方面)比使用递归更有效。

于 2013-06-19T18:56:00.873 回答