Выбор с предпочтением в SQL Server

У меня есть таблица в SQL Server 2000 с данными, подобными следующим:

ReferenceNumber    ReferenceValue
00001              Not assigned
00002              Not assigned
00002              ABCDE

в котором каждый ReferenceNumber может появляться в таблице несколько раз, либо со значением ReferenceValue, равным «Не назначено», либо с истинным значением ReferenceValue.

Я хочу сбросить данные в очищенную таблицу только с одной строкой для каждого ReferenceNumber и истинным ReferenceValue, если он существует, или «Не назначено», если нет истинных ReferenceValues.

Я вижу, как это сделать с двумя запросами:

SELECT TOP 1 ReferenceNumber, ReferenceValue
INTO clean
FROM duplicates
WHERE ReferenceValue <> 'Not assigned'

INSERT INTO clean(ReferenceNumber, ReferenceValue)
SELECT TOP 1 ReferenceNumber, ReferenceValue
WHERE ReferenceValue = 'Not assigned' 
AND ReferenceNumber NOT IN (SELECT ReferenceNumber FROM clean)

но я думаю, что должен быть лучший способ. Любые идеи?


person taserian    schedule 22.10.2009    source источник


Ответы (2)


Что-то вроде этого:

SELECT 
  ReferenceNumber
, ReferenceValue = ISNULL(MAX(NULLIF(ReferenceValue,'Not assigned')),'Not assigned')
INTO Table1_Clean
FROM Table1
GROUP BY
  ReferenceNumber

MAX() игнорирует NULL, поэтому сначала преобразуйте все, что вам не нужно, в NULL, затем MAX(), а затем преобразуйте NULL обратно в фиктивное значение.

Один проход в линию не может быть намного эффективнее.

person Peter Radocchia    schedule 22.10.2009

Для SQL SERVER 2000 это, вероятно, проще всего. Первое предложение = «реальные» значения, второе предложение не найдено в первом предложении. И продолжение вашей идеи.

SELECT d2.ReferenceNumber, d2.ReferenceValue
FROM duplicates d2
WHERE d2.ReferenceValue <> 'Not assigned'
UNION ALL
SELECT d1.ReferenceNumber, d1.ReferenceValue
FROM duplicates d1
WHERE NOT EXISTS (SELECT *
         FROM duplicates d2
         WHERE d2.ReferenceNumber = d1.ReferenceNumber AND
                 d2.ReferenceValue <> 'Not assigned')

Однако по каким критериям вы хотите установить связь между «истинными» эталонными значениями? или просто выбрать один?

person gbn    schedule 22.10.2009
comment
Для этой конкретной проблемы ReferenceNumber будет либо иметь «Не назначено», либо иметь уникальное ReferenceValue, поэтому проблем со связями нет. - person taserian; 22.10.2009
comment
@taserian: удалил мой агрегат - person gbn; 22.10.2009
comment
Я сохранил агрегат, поскольку, хотя RefNumber может иметь одно истинное RefValue, эта пара RefNumber-RefValue может появляться в таблице несколько раз. - person taserian; 22.10.2009
comment
Это три чтения и самосоединение, где вам нужно только одно чтение и никаких объединений. - person Peter Radocchia; 23.10.2009
comment
@gbn: вы имели в виду параллельное выполнение, когда предлагали этот метод? - person Peter Radocchia; 25.10.2009
comment
@Питер: нет. Просто для ясности. Я понимаю ваше решение (я проголосовал), но, надеюсь, мое решение более ясное и очевидное. - person gbn; 25.10.2009
comment
@gbn: как вы думаете, будет ли это использовать параллельное чтение? Я думаю, что это может быть для чтения и соединения, но у меня есть слепое пятно для параллелизма, и я действительно не знаю, как измерить относительную стоимость по сравнению с промежуточной катушкой. Ремус указал на возможность здесь: title="выбрать и объединить строки в таблице в хранимой процедуре sql"> stackoverflow.com/questions/1618560/. Раньше я был уверен, теперь нет. - person Peter Radocchia; 25.10.2009
comment
@Питер: черт возьми. Я не знаю. Тем не менее, буферизация может быть дорогостоящей и часто одной из самых сложных вещей для настройки. Я думаю, это зависит от: индексов, количества строк, соответствует ли стоимость параллельному порогу и т. д. - person gbn; 25.10.2009
comment
@gbn: я ценю обсуждение. Спасибо! - person Peter Radocchia; 25.10.2009