Могу ли я использовать оператор CASE в состоянии JOIN?
Следующее изображение является частью системных представлений Microsoft SQL Server 2008 R2. Из изображения видно, что отношения между sys.partitions
и sys.allocation_units
зависят от значения sys.allocation_units.type
. Чтобы объединить их, я бы написал что-то похожее на это:
SELECT *
FROM sys.indexes i
JOIN sys.partitions p
ON i.index_id = p.index_id
JOIN sys.allocation_units a
ON CASE
WHEN a.type IN (1, 3)
THEN a.container_id = p.hobt_id
WHEN a.type IN (2)
THEN a.container_id = p.partition_id
END
Но верхний код дает синтаксическую ошибку. Я предполагаю, что из-за заявления CASE
. Может кто-нибудь помочь объяснить немного?
Добавить сообщение об ошибке:
Сообщение 102, Уровень 15, Состояние 1, Строка 6 Неверный синтаксис рядом с '='.
![this is the image]()
Ответы
Ответ 1
A CASE
выражение возвращает значение из части THEN
в предложении. Вы можете использовать его таким образом:
SELECT *
FROM sys.indexes i
JOIN sys.partitions p
ON i.index_id = p.index_id
JOIN sys.allocation_units a
ON CASE
WHEN a.type IN (1, 3) AND a.container_id = p.hobt_id THEN 1
WHEN a.type IN (2) AND a.container_id = p.partition_id THEN 1
ELSE 0
END = 1
Обратите внимание, что вам нужно что-то сделать с возвращаемым значением, например. сравните его с 1. Ваше выражение попыталось вернуть значение задания или теста для равенства, ни одно из которых не имеет смысла в контексте предложения CASE
/THEN
. (Если BOOLEAN
был типом данных, тогда тест на равенство имел бы смысл.)
Ответ 2
Вместо этого вы просто ПРИСОЕДИНЯЕТЕСЬ к обеим таблицам, и в своем предложении SELECT возвращаете данные из той, которая соответствует:
Я предлагаю вам пройти по этой ссылке Условные объединения в SQL Server и Оператор T-SQL в предложении JOIN ON
например
SELECT *
FROM sys.indexes i
JOIN sys.partitions p
ON i.index_id = p.index_id
JOIN sys.allocation_units a
ON a.container_id =
CASE
WHEN a.type IN (1, 3)
THEN p.hobt_id
WHEN a.type IN (2)
THEN p.partition_id
END
Изменение: в соответствии с комментариями.
Вы не можете указать условие соединения, как вы делаете.. Проверьте запрос выше, без ошибок. Я вынул общий столбец вверх, и значение правильного столбца будет оценено при условии.
Ответ 3
Попробуйте следующее:
...JOIN sys.allocation_units a ON
(a.type=2 AND a.container_id = p.partition_id)
OR (a.type IN (1, 3) AND a.container_id = p.hobt_id)
Ответ 4
Я думаю, что вам нужно два случая:
SELECT *
FROM sys.indexes i
JOIN sys.partitions p
ON i.index_id = p.index_id
JOIN sys.allocation_units a
ON
-- left side of join on statement
CASE
WHEN a.type IN (1, 3)
THEN a.container_id
WHEN a.type IN (2)
THEN a.container_id
END
=
-- right side of join on statement
CASE
WHEN a.type IN (1, 3)
THEN p.hobt_id
WHEN a.type IN (2)
THEN p.partition_id
END
Это потому что:
- оператор CASE возвращает одно значение в конце
- оператор ON сравнивает два значения
- ваш оператор CASE делал сравнение внутри оператора CASE. Я полагаю, что если вы поместите свой оператор CASE в свой SELECT, вы получите логическое значение "1" или "0", указывающее, был ли оператор CASE оценен как True или False
Ответ 5
Это кажется приятным
https://bytes.com/topic/sql-server/answers/881862-joining-different-tables-based-condition
FROM YourMainTable
LEFT JOIN AirportCity DepCity ON @TravelType = 'A' and DepFrom = DepCity.Code
LEFT JOIN AirportCity DepCity ON @TravelType = 'B' and SomeOtherColumn = SomeOtherColumnFromSomeOtherTable
Ответ 6
Я взял твой пример и отредактировал его:
SELECT *
FROM sys.indexes i
JOIN sys.partitions p
ON i.index_id = p.index_id
JOIN sys.allocation_units a
ON CASE
WHEN a.type IN (1, 3)
THEN p.hobt_id
WHEN a.type IN (2)
THEN p.partition_id
ELSE NULL
END = a.container_id
Ответ 7
Здесь я сравнил разницу в двух разных наборах результатов. Надеюсь, это может быть полезно.
SELECT main.ColumnName, compare.Value PreviousValue, main.Value CurrentValue
FROM
(
SELECT 'Name' AS ColumnName, 'John' as Value UNION ALL
SELECT 'UserName' AS ColumnName, 'jh001' as Value UNION ALL
SELECT 'Department' AS ColumnName, 'HR' as Value UNION ALL
SELECT 'Phone' AS ColumnName, NULL as Value UNION ALL
SELECT 'DOB' AS ColumnName, '1993-01-01' as Value UNION ALL
SELECT 'CreateDate' AS ColumnName, '2017-01-01' as Value UNION ALL
SELECT 'IsActive' AS ColumnName, '1' as Value
) main
INNER JOIN
(
SELECT 'Name' AS ColumnName, 'Rahul' as Value UNION ALL
SELECT 'UserName' AS ColumnName, 'rh001' as Value UNION ALL
SELECT 'Department' AS ColumnName, 'HR' as Value UNION ALL
SELECT 'Phone' AS ColumnName, '01722112233' as Value UNION ALL
SELECT 'DOB' AS ColumnName, '1993-01-01' as Value UNION ALL
SELECT 'CreateDate' AS ColumnName, '2017-01-01' as Value UNION ALL
SELECT 'IsActive' AS ColumnName, '1' as Value
) compare
ON main.ColumnName = compare.ColumnName AND
CASE
WHEN main.Value IS NULL AND compare.Value IS NULL THEN 0
WHEN main.Value IS NULL AND compare.Value IS NOT NULL THEN 1
WHEN main.Value IS NOT NULL AND compare.Value IS NULL THEN 1
WHEN main.Value <> compare.Value THEN 1
END = 1
Ответ 8
Взял пример DonkeyKong.
Проблема в том, что мне нужно было использовать объявленную переменную. Это позволяет указать левую и правую стороны того, что вам нужно сравнить. Это для поддержки отчета SSRS, где различные поля должны быть связаны на основе выбора пользователем.
Первоначальный случай устанавливает выбор поля на основе выбора, а затем я могу установить поле, которое мне нужно сопоставить для объединения.
Второй оператор case может быть добавлен для правой части, если переменная необходима для выбора из разных полей
LEFT OUTER JOIN Dashboard_Group_Level_Matching ON
case
when @Level = 'lvl1' then cw.Lvl1
when @Level = 'lvl2' then cw.Lvl2
when @Level = 'lvl3' then cw.Lvl3
end
= Dashboard_Group_Level_Matching.Dashboard_Level_Name