SQL Left Outer Join не дает полную таблицу - PullRequest
3 голосов
/ 10 марта 2011

Я искал похожие проблемы, но ничего не нашел ...

У меня проблема с объединением двух таблиц в SQL. Первая таблица создается с использованием следующей процедуры

DECLARE @Sequence TABLE (n DATETIME NOT NULL)
DECLARE @Index INT
SET @Index = 1
WHILE @Index <= 96 BEGIN 
    INSERT @Sequence (n) VALUES (DATEADD(Minute, @Index * 5, DATEADD(Hour, -8, '06-25-2010 00:00:00')))
    SET @Index = @Index + 1 
END

И когда я запускаю обычный запрос, например:

SELECT
    Sequence.n
FROM
    @Sequence as Sequence 

Я получаю то, что ожидаю - 96 строк со значениями DateTime с интервалом в 5 минут, заканчивающихся 06-25-2010 00:00:00 (позднее это значение будет заменено параметром в отчете SSRS, поэтому оно может выглядеть странно чтобы указать «конец» диапазона и использовать двойной DATEADD).

Теперь вторая таблица содержит значения, зарегистрированные контроллерами PLMC, и они также регистрируют одну запись за 5 минут (для pointID, но не усложняют ее, допустим, что существует один PointID).

Проблема в том, что иногда контроллер отключается, и для данной точки не регистрируется никакого значения, даже 0. Вот почему, если я хочу получить полную картину последних 8 часов из любой заданной точки, я подошел с этой таблицей последовательности. Итак, если я возьму значения из другой таблицы в том же временном диапазоне, используя этот запрос:

SELECT
    DataTime, DataValue
FROM
    PointValue
WHERE
    PointValue.DataTime > DATEADD(Hour, -8, '06-22-2010 00:00:00')
    AND PointValue.DataTime < '06-22-2010 00:00:00'
    AND PointID = '5284'

Я получу только 56 строк. Это связано с тем, что после 20:30 в этот день контроллер перешел в автономный режим и записи не зарегистрированы.

Так вот в чем проблема. Я пытаюсь выполнить этот запрос, чтобы получить одно значение каждые 5 минут, и, надеюсь, по-прежнему видеть все 96 строк (8 часов с интервалами в 5 минут) с нулевыми значениями после 20: 30:

SELECT
    Sequence.n,
    PointValue.DataValue 
FROM
    @Sequence as Sequence LEFT OUTER JOIN PointValue 
    ON Sequence.n = PointValue.DataTime 
WHERE 
    PointID = '5280'

К сожалению, результат по-прежнему равен 56 строкам с теми же временными метками, что и у последнего запроса ... Я перепробовал каждое возможное соединение и не могу получить значения Нуль за последние 3,5 часа дня. , Я уверен, что совершаю очень простую ошибку, но я уже часами пробую разные способы ее решить, и мне серьезно нужна помощь.

РЕШИТЬ: Спасибо за ваши комментарии, я начал изменять запрос после прочтения первого комментария Blorgbeard. Все, что мне нужно было сделать, это сделать умножение на карте для моей временной последовательности на все релевантные pointID (поскольку мне не нужны все), поэтому в результате мой «FROM» выглядит следующим образом:

(SELECT Sequence.n, dbo.LABELS.theIndex FROM @TimeSequence as Sequence, dbo.LABELS
WHERE LEFT(dbo.LABELS.theLabel,2)='VA') as BaseTable
LEFT OUTER JOIN PointValue ON BaseTable.n = PointValue.DataTime AND BaseTable.theIndex = PointValue.PointID 

Еще раз спасибо за помощь!

Ответы [ 3 ]

8 голосов
/ 10 марта 2011

Вам необходимо переместить сравнение PointID в предложение ON - с его помощью в предложении WHERE вы заставляете LEFT JOIN стать INNER JOIN:

ON Sequence.n = PointValue.DataTime AND
   PointValue.PointID = '5280'

Условия в предложении WHERE имеют для каждой строки в наборе результатов.

4 голосов
/ 10 марта 2011

Я думаю, что проблема:

WHERE 
   PointID = '5280'

Поскольку PointID находится в таблице PointValue, для пропущенных строк он будет null, а null не равен '5280'.

Я думаю, что вы можете изменить это так, чтобы оно заработало:

WHERE 
   (PointID is null) or (PointID = '5280')
2 голосов
/ 10 марта 2011

Это потому, что в ваших пустых строках PointID не равен '5280'.

Попробуйте добавить это в предложение JOIN ...

ON Sequence.n = PointValue.DataTime AND PointID = '5280'
...