首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DATEPART修复日

DATEPART修复日
EN

Stack Overflow用户
提问于 2018-12-18 15:53:01
回答 2查看 144关注 0票数 2
代码语言:javascript
复制
CASE WHEN DAY % 2 = 0 AND POL = 'SUUA'
THEN CONVERT(VARCHAR(15),DATEPART(DAY,5)) + ' TO ' + CONVERT(VARCHAR(15),DATEPART(DAY,3),103)

我把日期放在第一位,但我不能改进它。我很抱歉信息少了。我在使用SQL Server。我上传了.img作为例子。

CASE WHEN DAY % 2 = 0 AND POL = 'SUUA' THEN CONVERT(VARCHAR(15),DATEPART(DAY,5)) + ' TO ' + CONVERT(VARCHAR(15),DATEPART(DAY,3),103)

我想表现得像这样

代码语言:javascript
复制
PORT            COLLECT             DEPARTURE

MANAUS      07/12 TO 12/12     15/12/2018(ODD DAY)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-12-18 19:31:15

为此,我强烈建议使用日历表。日历表保存有附加信息的日期值,因此更容易找到特定的日期(如本例所示的工作日或工作日)。

下面的解决方案使用一个日历表和2个CROSS APPLY操作符来获取以前的收集日期。

您可以这样创建日历表(递归CTE):

代码语言:javascript
复制
SET DATEFIRST 1 -- 1: Monday, 7: Sunday

-- Create a Calendar Table
IF OBJECT_ID('tempdb..#CalendarTable') IS NOT NULL
    DROP TABLE #CalendarTable

;WITH CalendarTable AS
(
    SELECT
        Date = CONVERT(DATE, '2016-01-01'),
        Weekday = DATEPART(WEEKDAY, '2016-01-01')

    UNION ALL

    SELECT
        Date = DATEADD(DAY, 1, C.Date),
        Weekday = DATEPART(WEEKDAY, DATEADD(DAY, 1, C.Date))
    FROM
        CalendarTable AS C
    WHERE
        C.Date <= '2020-01-01'
)
SELECT
    C.Date,
    C.Weekday
INTO
    #CalendarTable
FROM
    CalendarTable AS C
OPTION
    (MAXRECURSION 0)

该表如下:

代码语言:javascript
复制
SELECT * FROM #CalendarTable ORDER BY Date DESC

Date        Weekday
2020-01-02  4
2020-01-01  3
2019-12-31  2
2019-12-30  1
2019-12-29  7
2019-12-28  6
2019-12-27  5
2019-12-26  4
2019-12-25  3
2019-12-24  2
2019-12-23  1
2019-12-22  7
2019-12-21  6
2019-12-20  5
2019-12-19  4
2019-12-18  3
2019-12-17  2
2019-12-16  1
2019-12-15  7
2019-12-14  6
2019-12-13  5
2019-12-12  4
2019-12-11  3

我们将用这个来找最近的星期三和星期一,就在一个特定的出发日期之前。我们使用CROSS APPLYDepartureDate作为更高的限制,然后搜索特定的工作日(周一为1,周三为3)。然后使用TOP 1ORDER BY Date DESC,在出发日期之前的周一/周三获得最高值。

代码语言:javascript
复制
-- Build your Collect periods
;WITH SampleData AS
(
    SELECT
        V.Departure
    FROM
        (VALUES
            ('2018-12-01'),
            ('2018-12-09'),
            ('2018-12-25'),
            ('2018-12-29'),
            ('2019-01-02'),
            ('2019-01-07'),
            ('2019-01-10')) AS V(Departure)
)
SELECT
    V.Departure,

    -- Friday to Wednesday
    ClosestWednesdayBeforeDeparture = W.Date,
    PreviousFridayOfThatWednesday = DATEADD(DAY, -5, W.Date),

    -- Wednesday to Monday
    ClosestMondayBeforeDeparture = M.Date,
    PreviousWednesdayOfThatMonday = DATEADD(DAY, -5, M.Date),

    -- Check for odd/even
    IsOdd = CASE WHEN DATEPART(DAY, V.Departure) % 2 = 1 THEN 1 ELSE 0 END,

    -- Use previous expressions to build your collect periods
    Collect = CASE
        WHEN 
            DATEPART(DAY, V.Departure) % 2 = 1 -- IsOdd
        THEN
            CONVERT(VARCHAR(100), DATEADD(DAY, -5, W.Date), 120) -- PreviousFridayOfThatWednesday
            + ' TO '
            + CONVERT(VARCHAR(100), W.Date, 120) -- ClosestWednesdayBeforeDeparture

        ELSE -- IsEven
            CONVERT(VARCHAR(100), DATEADD(DAY, -5, M.Date), 120) -- PreviousWednesdayOfThatMonday
            + ' TO '
            + CONVERT(VARCHAR(100), M.Date, 120) -- ClosestMondayBeforeDeparture
        END
FROM
    SampleData AS V
    CROSS APPLY (
        SELECT TOP 1
            C.Date
        FROM
            #CalendarTable AS C
        WHERE
            C.Date < V.Departure AND
            C.Weekday = 3 -- 3: Wednesday
        ORDER BY
            C.Date DESC) AS W
    CROSS APPLY (
        SELECT TOP 1
            C.Date
        FROM
            #CalendarTable AS C
        WHERE
            C.Date < V.Departure AND
            C.Weekday = 1 -- 1: Monday
        ORDER BY
            C.Date DESC) AS M
ORDER BY
    V.Departure

从周三找到前一个星期五就像往后退5天一样简单,从周一到周三也是如此。

结果:

代码语言:javascript
复制
Departure   IsOdd   Collect                     ClosestWednesdayBeforeDeparture     PreviousFridayOfThatWednesday   ClosestMondayBeforeDeparture    PreviousWednesdayOfThatMonday
2018-12-01  1       2018-11-23 TO 2018-11-28    2018-11-28                          2018-11-23                      2018-11-26                      2018-11-21
2018-12-09  1       2018-11-30 TO 2018-12-05    2018-12-05                          2018-11-30                      2018-12-03                      2018-11-28
2018-12-25  1       2018-12-14 TO 2018-12-19    2018-12-19                          2018-12-14                      2018-12-24                      2018-12-19
2018-12-29  1       2018-12-21 TO 2018-12-26    2018-12-26                          2018-12-21                      2018-12-24                      2018-12-19
2019-01-02  0       2018-12-26 TO 2018-12-31    2018-12-26                          2018-12-21                      2018-12-31                      2018-12-26
2019-01-07  1       2018-12-28 TO 2019-01-02    2019-01-02                          2018-12-28                      2018-12-31                      2018-12-26
2019-01-10  0       2019-01-02 TO 2019-01-07    2019-01-09                          2019-01-04                      2019-01-07                      2019-01-02

这是一个很好的SQL练习。

票数 3
EN

Stack Overflow用户

发布于 2018-12-18 23:15:25

非常感谢埃兹洛,那真是太棒了。这是一个很好的SQL练习。我认为这很适合我的工作。很抱歉看上去很无聊,我有一些问题:

编辑:.我注意到V(出发)的日期是固定的。我想把日期做得很棒。因为当我把时间安排在

代码语言:javascript
复制
CROSS APPLY(SELECT TOP 1 
            C.DATE
        FROM 
            #CALENDARTABLE C, SAMPLEDATA V
        WHERE
            C.DATE < V.DEPARTURE AND
            C.WEEKDAY = 1 
        ORDER BY
            C.DATE DESC) AS W

CROSS APPLY (SELECT TOP 1
            C.DATE
        FROM
            #CALENDARTABLE C,SAMPLEDATA V
        WHERE
            C.DATE < V.DEPARTURE AND
            C.WEEKDAY = 7 
        ORDER BY
            C.DATE DESC) AS M

所有港口的收货日期。抱歉如果我无聊的话。你们帮了很多忙。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53836703

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档