2017-09-14 84 views
0

請原諒我,如果這聽起來不錯,我不是SQL的專家。SQL - 將日期時間列設置爲最近的工作日

所以我有幾個存儲過程插入或更新特定的表。

目前,對於每個存儲過程,對於特定的日期時間列(我們稱之爲MailingDate),在select子句中使用各種case語句將其設置爲星期五或星期六,這取決於什麼週末日期。只是一個參照系,即邏輯是這樣的:

alias.MailingDate = 
CASE DATEPART(WEEKDAY, DATEADD(dd, aliasTwo.MailingDays, aliasThree.DateScheduled)) 
    WHEN 7 THEN 
      CASE aliasTwo.MailingDays 
       WHEN 0 THEN DATEADD(DAY, 2, DATEADD(dd, aliasTwo.MailingDays, aliasThree.DateScheduled)) -- Saturday is 7, MailingDate fell on Saturday the 1st, goto Monday. 
       ELSE DATEADD(DAY, -1, DATEADD(dd, aliasTwo.MailingDays, aliasThree.DateScheduled))  -- Saturday is 7, MailingDate fell on Saturday, goto Friday. 
      END 
    WHEN 1 THEN DATEADD(DAY, 1, DATEADD(dd, aliasTwo.MailingDays, aliasThree.DateScheduled))    -- Sunday is 1, MailingDate needs to goto Monday. 
    ELSE DATEADD(dd, aliasTwo.MailingDays, aliasThree.DateScheduled)          -- MailingDate fell on Weekday. 
END, -- MailingDate 

從本質上講,我不得不更換邏輯考慮到這一點:

有一個配置表(無PK-> FK關係任何其他表)看起來是這樣的(在值列中的項目隨時可以改變,因爲我們的目標是爲它是動態的):

Configurations: 

|ConfigurationId|  Keyword  |  Value   | 
------------------------------------------------------------ 
|1    |MailingDays:Sunday |Value1    | 
|2    |MailingDays:Monday |     | 
|3    |MailingDays:Tuesday |Value2    | 
|4    |MailingDays:Wednesday|Value3|Value1  | 
|5    |MailingDays:Thursday |     | 
|6    |MailingDays:Friday |Value1|Value2|Value3| 
|7    |MailingDays:Saturday |Value3|Value1  | 

的每一行代表一個工作日,在每個工作日有是一個varchar()Value列,它包含一個以管道分隔的lis來自另一個表的varchar()值。這個想法是,當你如上所述更新郵件日期時,我需要動態地使用這個表來檢查每個特定值(值1,值2,值3),每個值歸屬於哪個工作日,並將郵件日期移動到最近的工作日。

例如,如果我計算歸屬於Value1的所有郵寄日期,則需要動態搜索配置表,請參閱Value1歸因於星期日,星期三,星期五和星期六,並將其移至根據aliasTwo.MailingDays的週日計算的最接近的週日。在這種情況下,如果aliasTwo.MailingDays是星期一,則必須將alias.MailingDate設置爲星期日。而如果aliasTwo.MailingDays是星期二,我將不得不將alias.MailingDate移動到星期三。

有一個特殊的使用情況,如果alias.MailingDays是工作日它是其他兩個工作日之間的距離相等:

例如,如果我在尋找值2的配置表,我會看到值2歸因到週二和週五。因此,在這種情況下,如果aliasTwo.MailingDays是一個星期天,那麼alias.MailingDate將轉到它歸因於的下一個工作日。在這種情況下,由於星期日和星期二的星期日等距,所以它會前進到星期二。

這基本上是需要發生的。 SQL絕對不是我最強的語言,所以對這個問題的任何有益的幫助將不勝感激。

如果您需要進一步澄清,請讓我知道。

謝謝!

回答

0

我會在幾天之間創建一個映射表,並在那一天移動到什麼位置。然後創建一個單獨的表映射到該日期映射的值。獲取擺脫你的超載列,並允許你只是保持那個日期映射表與什麼聽起來像很瘋狂的日期轉換邏輯

if object_id('tempdb.dbo.#DateMappings') is not null drop table #DateMappings 
create table #DateMappings 
(
    MappingId int identity(1,1), 
    ThisDOW int, 
    MapsToThisDOW int 

    primary key clustered (MappingId), 
    unique (THisDOw, MapsToTHisDOW) 
) 

-- This would be replaced with what your actual logic is; i'm not going to try to figure out your rules 
;with nums (num) as 
(
    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 
) 
insert into #DateMappings 
(
    ThisDOW, 
    MapsToThisDOW 
) 
select 
    ThisDOW = a.num, 
    MapsToThisDOW = b.num 
from nums a 
cross join nums b 

if object_id('tempdb.dbo.#ValueDateMappings') is not null drop table #ValueDateMappings 
create table #ValueDateMappings 
(
    Value varchar(100), 
    DateMappingId int 

    primary key clustered (Value, DateMappingId) 
) 

-- This maps a SINGLE value to a SINGLE mapping construct. You can then use the information for that date mapping to construct or adjust the mailing date as you see fit 
insert into #ValueDateMappings 
values 
    ('Value 1', 1), 
    ('value 1', 3) 
    -- ...etc