我在datepart方面需要很少的帮助。 我有两列{DEPARTURE_DATE}和{COLLECT_DAYS}。 如果从Deaparture_Date列中得出奇数天,则在 周三至周一,赔率天应在周五至周三。我尝试了这个:
CASE WHEN DAY % 2 = 0 AND POL = 'SUUA'
THEN CONVERT(VARCHAR(15),DATEPART(DAY,5)) + ' TO ' + CONVERT(VARCHAR(15),DATEPART(DAY,3),103)
我将datefirst设置为1,但是我无法改善这一点。 抱歉,信息不足。我正在使用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)
我想展示这样的东西
PORT COLLECT DEPARTURE
MANAUS 07/12 TO 12/12 15/12/2018(ODD DAY)
请参阅此处,收集时间应为星期五至星期三
答案 0 :(得分:3)
我强烈建议为此使用日历表。日历表包含带有其他信息的日期值,因此更容易查找特定的日期(例如本示例中的工作日或工作日)。
以下解决方案使用日历表和2个CROSS APPLY
运算符来获取以前的收集日期。
这是创建日历表(递归CTE)的方法:
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)
表如下:
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 APPLY
作为上限的DepartureDate
来找到它,然后搜索特定的工作日(星期一为1,星期三为3)。然后将TOP 1
与ORDER BY Date DESC
一起使用,以获取该出发日期之前的最高星期一/星期三。
-- 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天一样简单,从星期一到星期三也是如此。
结果:
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练习。
答案 1 :(得分:0)
非常感谢@Ezlo,那就太好了。这是一个很好的SQL练习。我认为这很适合我的工作。对不起,看起来很无聊,我有一些问题:
编辑:。我注意到V(离场)的日期是固定的。我想使日期动感。因为当我设置日期
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
所有端口的修复日期收集。 对不起,如果我无聊。你们帮了很多忙。