Левое внешнее объединение в SQL Server 2012 LocalDB не работает?
Используя SQL Server 2012 (LocalDB), у меня есть три таблицы:
BESEXT.COMPUTER
BESEXT.ANALYSIS_PROPERTY
BESEXT.ANALYSIS_PROPERTY_RESULT
Это содержит следующую информацию:
- BESEXT.COMPUTER: сопоставление между идентификаторами компьютеров и именами компьютеров
- BESEXT.ANALYSIS_PROPERTY: список свойств, которые могут быть сопоставлены с компьютером
- BESEXT.ANALYSIS_PROPERTY_RESULT: список значений свойств для компьютера
Сначала я выполняю следующий запрос:
SELECT
AR.ComputerID,
AP.Name,
AR.Value
FROM BESEXT.ANALYSIS_PROPERTY_RESULT AR
JOIN BESEXT.ANALYSIS_PROPERTY AP ON AP.ID = AR.PropertyID
AND AP.ID IN (1672, 1673, 1674)
ORDER BY AR.ComputerID, AP.Name
Что дает следующий результат:
ComputerID Name Value
---------- ---- -----
595640 DisplayName Windows 8.1 x64 - Mobile Device Image - v3.2
595640 SequenceName Windows 8.1 x64 - Mobile Device Image
595640 SequenceVersion 3.2
631459 DisplayName Windows 8.1 x64 - Mobile Device Image - v3.2
631459 SequenceName Windows 8.1 x64 - Mobile Device Image
631459 SequenceVersion 3.2
В BESEXT.COMPUTER у меня есть следующие значения:
ID ComputerID ComputerName
-- ---------- ------------
1 595640 PO121203866
2 631459 PO121201739
3 1101805 PO121201100
Я хочу выполнить левое внешнее объединение всех моих компьютерных объектов при первом выборе, чтобы я знал, для каких компьютеров у меня нет значения.
Итак, сначала я делаю простое внутреннее соединение с предыдущим выбором:
SELECT
C.ComputerName,
R.ComputerID,
R.Name,
R.Value
FROM (
SELECT
AR.ComputerID,
AP.Name,
AR.Value
FROM BESEXT.ANALYSIS_PROPERTY_RESULT AR
JOIN BESEXT.ANALYSIS_PROPERTY AP ON AP.ID = AR.PropertyID
AND AP.ID IN (1672, 1673, 1674)
) R
JOIN BESEXT.COMPUTER C ON C.ComputerID = R.ComputerID
ORDER BY R.ComputerID, R.Name
Что, как и ожидалось, дает следующий набор результатов:
ComputerName ComputerID Name Value
------------ ---------- ---- -----
PO121203866 595640 DisplayName Windows 8.1 x64 - Mobile Device Image - v3.2
PO121203866 595640 SequenceName Windows 8.1 x64 - Mobile Device Image
PO121203866 595640 SequenceVersion 3.2
PO121201739 631459 DisplayName Windows 8.1 x64 - Mobile Device Image - v3.2
PO121201739 631459 SequenceName Windows 8.1 x64 - Mobile Device Image
PO121201739 631459 SequenceVersion 3.2
Теперь, для грандиозного финала, давайте сделаем LEFT OUTER JOIN:
SELECT
C.ComputerName,
R.ComputerID,
R.Name,
R.Value
FROM (
SELECT
AR.ComputerID,
AP.Name,
AR.Value
FROM BESEXT.ANALYSIS_PROPERTY_RESULT AR
JOIN BESEXT.ANALYSIS_PROPERTY AP ON AP.ID = AR.PropertyID
AND AP.ID IN (1672, 1673, 1674)
) R
-- LEFT OUTER JOIN ADDED HERE!
LEFT OUTER JOIN BESEXT.COMPUTER C ON C.ComputerID = R.ComputerID
ORDER BY R.ComputerID, R.Name
Это дает тот же набор результатов, что и при внутреннем соединении!
Это не то, что я ищу, и это совсем не то, что я ожидал. Сейчас уже довольно поздно, и я в основном делаю какую-то работу из-за бессонницы, но я думаю, что это примерно такой же простой пример внешнего соединения, как это возможно, не так ли? Результат, которого я хочу достичь с помощью внешнего соединения, таков:
ComputerName ComputerID Name Value
PO121203866 595640 DisplayName Windows 8.1 x64 - Mobile Device Image - v3.2
PO121203866 595640 SequenceName Windows 8.1 x64 - Mobile Device Image
PO121203866 595640 SequenceVersion 3.2
PO121201739 631459 DisplayName Windows 8.1 x64 - Mobile Device Image - v3.2
PO121201739 631459 SequenceName Windows 8.1 x64 - Mobile Device Image
PO121201739 631459 SequenceVersion 3.2
PO121201100 NULL NULL NULL
PO121201100 NULL NULL NULL
PO121201100 NULL NULL NULL
PS: Если честно, результат, который я ищу, больше похож на этот, но я чувствую, что это был бы совсем другой вопрос:
ComputerName Name Value
------------ ---- -----
PO121203866 DisplayName Windows 8.1 x64 - Mobile Device Image - v3.2
PO121203866 SequenceName Windows 8.1 x64 - Mobile Device Image
PO121203866 SequenceVersion 3.2
PO121201739 DisplayName Windows 8.1 x64 - Mobile Device Image - v3.2
PO121201739 SequenceName Windows 8.1 x64 - Mobile Device Image
PO121201739 SequenceVersion 3.2
PO121201100 DisplayName NULL
PO121201100 SequenceName NULL
PO121201100 SequenceVersion NULL
3 ответа
Запрос, который вы ищете, может быть написан просто так:
SELECT ComputerName, A.ComputerID, Name, Value FROM BESEXT.COMPUTER A
CROSS JOIN (SELECT * FROM BESEXT.ANALYSIS_PROPERTY WHERE ID BETWEEN 1672 AND 1674) B
LEFT JOIN BESEXT.ANALYSIS_PROPERTY_RESULT C ON A.ComputerId = C.ComputerId AND B.ID = C.PropertyId
ORDER BY ComputerId, Name
Начните с получения всех комбинаций компьютер-свойства, которые вас интересуют:
SELECT * FROM BESEXT.COMPUTER A
CROSS JOIN (SELECT * FROM BESEXT.ANALYSIS_PROPERTY WHERE ID BETWEEN 1672 AND 1674) B
Это дает результаты:
ID ComputerId ComputerName ID Name
-- ---------- ------------ -- ----
1 595640 PO121203866 1672 DisplayName
2 631459 PO121201739 1672 DisplayName
3 1101805 PO121201100 1672 DisplayName
1 595640 PO121203866 1673 SequenceName
2 631459 PO121201739 1673 SequenceName
3 1101805 PO121201100 1673 SequenceName
1 595640 PO121203866 1674 SequenceVersion
2 631459 PO121201739 1674 SequenceVersion
3 1101805 PO121201100 1674 SequenceVersion
Оттуда вы просто выполняете левое соединение BESEXT.ANALYSIS_PROPERTY_RESULT
чтобы получить ваши ценности, и вы включаете ORDER BY
пункт, чтобы отсортировать его.
Вы можете сделать это, используя перекрестное соединение, чтобы настроить свойства для всех компьютеров, а затем левое соединение, чтобы подключиться к фактическим значениям свойств для тех компьютеров, для которых установлены значения:
SELECT * FROM (
SELECT
C.ComputerName,
C.ComputerID,
AP.Name,
AP.ID
FROM BESEXT.COMPUTER C
CROSS JOIN BESEXT.ANALYSIS_PROPERTY AP
WHERE AP.ID IN (1672, 1673, 1674)
) AP
LEFT JOIN BESEXT.ANALYSIS_PROPERTY_RESULT AR
ON AP.ComputerID = AR.ComputerID AND AP.ID = AR.PropertyID
ORDER BY AP.ComputerName DESC, AP.Name
Как LOJ это будет так?
SELECT
R.ComputerName,
C.ComputerID,
C.Name,
C.Value
FROM BESEXT.COMPUTER R
-- LEFT OUTER JOIN ADDED HERE!
LEFT OUTER JOIN
(
SELECT
AR.ComputerID,
AP.Name,
AR.Value
FROM BESEXT.ANALYSIS_PROPERTY_RESULT AR
JOIN BESEXT.ANALYSIS_PROPERTY AP ON AP.ID = AR.PropertyID
AND AP.ID IN (1672, 1673, 1674)
) C
ON C.ComputerID = R.ComputerID
ORDER BY C.ComputerID, C.Name