#sql-server #tsql #join #nested
#sql-server #tsql #Присоединиться #вложенный
Вопрос:
Мне нужно объединить два условия — первое простое, но второе, похоже, запрашивает вложенный оператор case, но я не смог понять, как заставить его работать или лучший вариант.
Проблема в том, что у меня есть действие, которое может происходить один или два раза в день. Если это происходит один раз в день, я могу просто присоединиться к дате. Если это происходит два раза в день, мне нужно соответствующим образом присоединиться из таблицы X в таблицу Y в зависимости от того, утро это или день, и при этом мне нужно в основном округлять кучу раз с утра и после обеда до одного значения для каждого для объединения.
Это отлично работает:
Inner join table x on x.ser = y.ser and (case when X <= 12 then 9 else
15) = (case when Y <= 12 then 9 else 15)
Но если я добавлю еще один оператор case вокруг оригинала, он все равно развалится и будет выглядеть как дерьмовый код, поэтому я полагаю, что должен быть лучший способ решить эту проблему, но он ускользает от меня.
case when (code = BID) then
(case when X <= 12 then 9 else 15) = (case when Y <= 12 then 9 else 15)
else X = Y
Фактический нерабочий код приведен ниже.
INNER JOIN dbo.Image img on img.Ser = sa.Ser and
case when (ac.ActivityCode = 'BID') then
CASE WHEN DATEPART(hour, img.CreationDate) <= 12 THEN
DATEADD(hh, 9, DATEADD(dd, DATEDIFF(dd, 0,
img.CreationDate), 0)) ELSE DATEADD(hh, 15, DATEADD(dd,
DATEDIFF(dd, 0, img.CreationDate), 0))
END = CASE WHEN DATEPART(hour, sa.ActualStartDate) <= 12 THEN
DATEADD(hh, 9, DATEADD(dd, DATEDIFF(dd, 0,
sa.ActualStartDate), 0)) ELSE DATEADD(hh, 15,
DATEADD(dd, DATEDIFF(dd, 0, sa.ActualStartDate),
0))
END
ELSE sa.ActualStartDate = img.CreationDate
END
Комментарии:
1. вы пытались разделить запрос на 2 запроса (один для одного действия, а другой для нескольких действий)? если нет, попробуйте сначала разделить их, получить правильные результаты для обоих запросов, затем просмотрите их оба и измените их настолько, насколько сможете, затем посмотрите, что вы можете сделать, чтобы объединить их оба в одном запросе.
2. Ваше предложение — это именно то, к чему я пришел. Я подумал, как вы советуете, что так легче добраться туда, куда я хочу. Также возникла еще одна вещь — пользователь сказал мне, что мой подход даст правильный ответ в 99% случаев, но было очень небольшое количество крайних случаев, когда он не будет работать, поэтому способ, который вы предлагаете, будет необходим в любом случае.
3. при разделении вы можете охватить все возможные случаи намного проще и быстрее, хотя иногда было бы необходимо использовать отдельный запрос для каждого случая. Таким образом, это не всегда решение с одним запросом.
Ответ №1:
Вы не можете иметь оператор сравнения {expression 1} = {expression 2}
внутри CASE
оператора.
Это должно быть что-то вроде
INNER JOIN dbo.Image img on img.Ser = sa.Ser
and CASE ... END = CASE ... END
Но тогда ваш запрос будет трудно прочитать. Почему бы не использовать a CTE
. И вычислите новое выражение внутри CTE
; WITH
CTE1 AS
(
Col2 = CASE WHEN DATEPART(hour, img.CreationDate) <= 12 .....
),
CTE2 AS
(
Col2 = CASE WHEN DATEPART(hour, sa.ActualStartDate) <= 12 .....
)
SELECT *
FROM CTE1 c1
JOIN CTE2 c2 ON c1.Ser = c2.Ser
AND c2.Col2 = c2.Col2