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)
Не могли бы вы подробнее рассказать о результатах и типах данных? Также отметьте, какую СУБД вы используете (я подозреваю, SQL Server). Что вы имеете в виду под фразой «дата отъезда должна быть со среды по понедельник»?
@BRKZ, вы можете использовать кнопку редактирования, чтобы добавить дополнительную информацию по вашему вопросу.
Прошу прощения за меньшую информацию. Я отредактировал и добавил информацию. Извините за мой английский. Надеюсь, ты понимаешь.
@BRKZ каковы ваши требования ??
Как вы определяете странный на основе дня недели или дня месяца? Понедельник среда пятница или 1/3/5/7 / ..
в зависимости от дня недели. Я использую DATEPART (Deaparture_Date) и получаю день месяца. Но я не могу применить это на case
Я настоятельно рекомендую использовать для этого календарный стол. Таблица календаря содержит значения дат с дополнительной информацией, поэтому легче найти определенные дни (например, рабочие или будние дни, как в этом примере).
Следующее решение использует календарную таблицу и 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.
Каждый раз, когда вы обнаруживаете, что делаете гораздо больше, чем просто вычисление даты, вам, вероятно, следует подумать о календарной таблице. Фактически, каждый раз, когда у вас есть база данных, вам, вероятно, следует добавить таблицу календаря, а затем изменить ее по мере необходимости. И таблица календаря, и таблица чисел кажутся огромными отходами, но они могут легко и значительно повысить производительность. Это должно быть основной темой при проектировании или использовании любой базы данных. Я желаю, чтобы каждый раз, когда кто-то задавал вопрос о SQL (любой разновидности), спрашивал: «Пробовали ли вы календарную таблицу?» подсказка выскочила.
На самом деле спасибо @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
Даты сбора как фиксированные для всех портов. Извините, если мне скучно. Ребята, вы очень помогаете.
Таблица V
из моего примера - это SampleData
, которые представляют собой жестко запрограммированные значения, которые я использовал в качестве примера. Просто удалите CTE под названием SampleData
и замените FROM SampleData AS V
исходной таблицей, содержащей значения отклонений. Перекрестные применения не нуждаются в изменении (не нужно снова ссылаться на таблицу V
внутри перекрестного применения, просто это ссылка через C.Date < V.Departure
, это называется коррелированным подзапросом).
Большое спасибо @EzLo. Работает хорошо! Просто у меня небольшая проблема. Когда дата отъезда 25/12/2018 01:00:00, моя дата получения превышает дату отъезда. СОБИРАЙ ОТПРАВЛЕНИЕ 2018-12-24 TO 2018-12-29 - 25/12/2018 01:00:00
Но кросс, возможно, работает с других дат. CROSS APPLY (SELECT TOP 1 C.DATE FROM #CALENDARTABLE C WHERE C.DATE < CONVERT(DATE,ESCALA_ORIGEM.DATA_PREV_SAIDA) AND C.WEEKDAY = 7 ORDER BY C.DATE DESC) AS M
в опубликованном мною запросе есть пример 2018-12-25, у которого сбор не выше этой даты (2018-12-14 TO 2018-12-19). Может, какие-то редакции делали? Попробуйте преобразовать значения даты и времени в дату, прежде чем сравнивать их с календарной таблицей. Убедитесь, что правильный столбец - ESCALA_ORIGEM.DATA_PREV_SAIDA
. Попробуйте жестко запрограммировать дату и выполнить выбор, он не должен показывать дату выше 25.
Спасибо за уделенное время @EzLo. Очень помогает. Пытаюсь исправить дату 25.12.2018. Пока не удалось. Если исправлю, доложу сюда.
Я лечу паллиативно. Я сделал еще один случай только на ДЕНЬ (25). Наверное, в 2019 мне нужно будет обновить корпус.
Пожалуйста, предоставьте образцы данных и желаемые результаты. Описание не имеет особого смысла без примеров данных. Также отметьте используемую базу данных.