Оператор SQL для проверки на наличие NULLS и несуществующих записей - PullRequest
0 голосов
/ 25 ноября 2010

Я делаю соединение между двумя таблицами и хочу выбрать столбцы в зависимости от того, есть ли у них запись или нет. Я стараюсь избегать использования нескольких одинаковых полей и пытаюсь объединить их в отдельные столбцы. Что-то вроде:

Select 
    id = (CASE WHEN a.id IS NULL THEN b.id ELSE a.id END),
    name = (CASE WHEN a.name IS NULL THEN b.name ELSE a.name END)
From Table1 a
Left Join Table2 b
On a.id = b.id
Where a.id = @id

Я бы хотел, чтобы id заполнял с Table1, если запись существует, но если нет, извлекайте из Table2. Предыдущий код не возвращает записей, потому что в Table1 нет значений NULL, поэтому мой вопрос: как мне проверить, существуют ли какие-либо записи? Также, если кто-то знает, как лучше выполнить то, что я пытаюсь сделать, я ценю руководство и конструктивную критику.

EDIT

Похоже, COALESCE сработает для того, чего я пытаюсь достичь. Я хотел бы дать немного больше информации о том, с чем именно я работаю, и получить несколько советов о том, использую ли я лучший метод.

У меня раздутый стол Table2, и он в производстве. Я работаю над созданием новых веб-приложений для этой системы, но не могу оправдать полный редизайн базы данных, поэтому я пытаюсь сделать одно "на лету". Я создал новую таблицу Table1 и пишу хранимые процедуры для следующих методов Get (Select), Set (Update), Add (Insert), Remove (Delete). Таким образом, моему коду будет казаться, что я работаю с одной таблицей, которая не является раздутой. Мой код просто вызовет один из методов SP, а затем хранимая процедура обработает данные между старой таблицей и новой. В настоящее время я работаю над методом Get, и мне нужно проверить старую таблицу Table2 на наличие записи, если она не существует в Table1. Благодаря предложениям здесь мой запрос в настоящее время выглядит так:

Select
    id = coalesce(a.id, b.student_number),
    first_name = coalesce(a.first_name, b.first_name),
    last_name = coalesce(a.last_name, b.last_name),
    //etc
From Table1 a
Full Outer Join Table2 b
On a.id = b.student_number
Where (a.id = @id Or b.student_number = @id)

Это работает для того, чего я пытаюсь достичь, я хотел бы поделиться с ним опытной толпой за любые советы или предложения, если есть лучшие или более правильные способы сделать это.

Спасибо

Ответы [ 5 ]

1 голос
/ 25 ноября 2010

Я подозреваю, что ваша проблема может возникнуть из-за левого соединения.Попробуйте еще раз, используя полное внешнее объединение, например:

Select 
    id = coalesce(a.id, b.id),
    name = coalesce(a.name, b.name)
From Table1 a
full outer Join Table2 b
On a.id = b.id
Where a.id = @id
1 голос
/ 25 ноября 2010

Во-первых, вам не нужно указывать регистр для этого:

Select ISNULL(a.id,b.id) AS id, ISNULL(a.name,b.name) AS name,
From Table1 a
Left Join Table2 b
On a.id = b.id
Where a.id = @id

Во-вторых, если я правильно понял, поле id может содержать нули, и в этом случае вы облажались.Я имею в виду, что идентификатор - это уникальное значение, которое идентифицирует строку, если она может быть нулевой, вы не можете идентифицировать эту строку.

Но если вам нужно получить записи из таблиц Table1 и Table2 и избежать дубликатов,простой UNION будет работать нормально, так как отбрасывает дубликаты:

select id, name
from Table1
where id = @id

union

select id, name
from Table2
where id = @id
1 голос
/ 25 ноября 2010
Select id = coalesce(a.id, b.id), 
    name = coalesce(a.name, b.name)
From Table2 b 
Left Join Table1 a On a.id = b.id 
Where b.id = @id 

Возможно, вам придется использовать ISNULL или CASE вместо COALESCE в зависимости от платформы вашей базы данных.

0 голосов
/ 25 ноября 2010

В вашем первом операторе CASE a.id и b.id всегда будут иметь одинаковое значение, за исключением случаев, когда a.id имеет значение, а b.id генерирует значение NULL из-за LEFT JOIN. В результирующем наборе никогда не будет строки со значением NULL a.id и значением, отличным от NULL b.id. Вы можете просто использовать a.id для этого столбца.

Для второго оператора CASE вы можете найти столбец имени в одной или обеих таблицах со значением (и, конечно, значения могут отличаться). Вы сказали, что хотите «сжать» значения этих столбцов; функция SQL для этого является COALESCE:

 COALESCE(a.id, b.id)

, который возвращает первое ненулевое значение (a.id, если оно не NULL, иначе b.id). Это не даст вам подсказки к разным именам в двух таблицах.

0 голосов
/ 25 ноября 2010

Вы можете сделать что-то вроде:

выберите идентификатор, имя из таблицы 1, где a.id нет (выберите идентификатор из таблицы 2) UNION выберите идентификатор, имя из таблицы 2 b

Это даст вам все записи из таблицы1, которые не имеют соответствующего соответствия в таблице2, а также все записи таблицы2. Затем объединение объединит результаты.

...