Использование регистра в SQL-сервере

Я пытаюсь использовать оператор CASE в SQL Server. Я пытаюсь обновить столбец ProfitUSD, где значения, полученные из столбца Profit, умножаются на коэффициент конверсии из столбца Rate, чтобы получить Profit в долларах США (столбец ProfitUSD). По сути, я просто пытаюсь преобразовать прибыль в доллары США, умножив соответствующий коэффициент конверсии, полученный из столбца Rate.

Любая помощь могла бы быть полезна :)

Проблема здесь в том, что когда я запускаю это, я получаю следующую ошибку:

Сообщение 512, уровень 16, состояние 1, строка 1
Подзапрос вернул более 1 значения. Это не разрешено, когда подзапрос следует за =, !=, ‹, ‹= , >, >= или когда подзапрос используется как выражение. Заявление было прекращено

Код:

update dbo.[5 Mins]
set ProfitUSD =
    case
    when Region='AEX 30 Netherlands' then Profit*(select rate from dbo.rates where Region='AEX 30 Netherlands') 
    when Region='ASX Australia' then Profit*(select Rate from dbo.rates where Region='ASX Australia')
    when Region='Athens' then Profit*(select Rate from dbo.rates where Region='Athens')
    when Region='Austria' then Profit*(select Rate from dbo.rates where Region='Austria')
    when Region='Bahrain' then Profit*(select Rate from dbo.rates where Region='Bahrain')
    when Region='Bovespa' then Profit*(select Rate from dbo.rates where Region='Bovespa')
    when Region='Brussels' then Profit*(select Rate from dbo.rates where Region='Brussels')
    when Region='Bucharest' then Profit*(select Rate from dbo.rates where Region='Bucharest')
    when Region='Budapest' then Profit*(select Rate from dbo.rates where Region='Budapest')
    when Region='Bulgaria' then Profit*(select Rate from dbo.rates where Region='Bulgaria')
    when Region='CAC 40' then Profit*(select Rate from dbo.rates where Region='CAC 40')
    when Region='CBOT' then Profit*(select Rate from dbo.rates where Region='CBOT')
    when Region='CME Globex' then Profit*(select Rate from dbo.rates where Region='CME Globex')
    when Region='Comex Metal' then Profit*(select Rate from dbo.rates where Region='Comex Metal')
    when Region='Copanhagen' then Profit*(select Rate from dbo.rates where Region='Copanhagen')
    when Region='DJ Euro Stoxx 50' then Profit*(select Rate from dbo.rates where Region='DJ Euro Stoxx 50')
    when Region='Doha' then Profit*(select Rate from dbo.rates where Region='Doha')
    when Region='Egypt' then Profit*(select Rate from dbo.rates where Region='Egypt')
    when Region='FTSE'  then Profit*(select Rate from dbo.rates where Region='FTSE')
    when Region='FTSE Malaysia' then Profit*(select Rate from dbo.rates where Region='FTSE Malaysia')
    when Region='Hang Seng' then Profit*(select Rate from dbo.rates where Region='Hang Seng')
    when Region='Helsinki' then Profit*(select Rate from dbo.rates where Region='Helsinki')
    when Region='ICE Nybot' then Profit*(select Rate from dbo.rates where Region='ICE Nybot')
    when Region='ICEX Iceland' then Profit*(select Rate from dbo.rates where Region='ICEX Iceland')
    when Region='Istanbul' then Profit*(select Rate from dbo.rates where Region='Istanbul')
    when Region='Johannesberg' then Profit*(select Rate from dbo.rates where Region='Johannesberg')
    when Region='Lima' then Profit*(select Rate from dbo.rates where Region='Lima')
    when Region='Lisbon' then Profit*(select Rate from dbo.rates where Region='Lisbon')
    when Region='Moroccan' then Profit*(select Rate from dbo.rates where Region='Moroccan')
    when Region='Moscow' then Profit*(select Rate from dbo.rates where Region='Moscow')
    when Region='New Zeland NZX' then Profit*(select Rate from dbo.rates where Region='New Zeland NZX')
    when Region='Nigeria 30 Lagos' then Profit*(select Rate from dbo.rates where Region='Nigeria 30 Lagos')
    when Region='Nse All' then Profit*(select Rate from dbo.rates where Region='Nse All')
    when Region='Oman' then Profit*(select Rate from dbo.rates where Region='Oman')
    when Region='Oslo' then Profit*(select Rate from dbo.rates where Region='Oslo')
    when Region='Parague' then Profit*(select Rate from dbo.rates where Region='Parague')
    when Region='Philippines' then Profit*(select Rate from dbo.rates where Region='Philippines')
    when Region='Santiago' then Profit*(select Rate from dbo.rates where Region='Santiago')
    when Region='Saudi' then Profit*(select Rate from dbo.rates where Region='Saudi')
    when Region='Shanghai' then Profit*(select Rate from dbo.rates where Region='Shanghai')
    when Region='Slovenia' then Profit*(select Rate from dbo.rates where Region='Slovenia')
    when Region='Spain' then Profit*(select Rate from dbo.rates where Region='Spain')
    when Region='STI Singapore' then Profit*(select Rate from dbo.rates where Region='STI Singapore')
    when Region='Stockholm' then Profit*(select Rate from dbo.rates where Region='Stockholm')
    when Region='Swiss' then Profit*(select Rate from dbo.rates where Region='Swiss')
    when Region='Toronto' then Profit*(select Rate from dbo.rates where Region='Toronto')
    when Region='TSE Tokyo' then Profit*(select Rate from dbo.rates where Region='TSE Tokyo')
    when Region='Tunisia' then Profit*(select Rate from dbo.rates where Region='Tunisia')
    when Region='Turquise Italy' then Profit*(select Rate from dbo.rates where Region='Turquise Italy')
    when Region='Warsaw' then Profit*(select Rate from dbo.rates where Region='Warsaw')
    when Region='NASDAQ 100' then Profit*(select Rate from dbo.rates where Region='NASDAQ 100')
    when Region='Abu Dhabi' then Profit*(select Rate from dbo.rates where Region='Abu Dhabi')
    when Region='Nordic' then Profit*(select Rate from dbo.rates where Region='Nordic')
    when Region='NYSE All' then Profit*(select Rate from dbo.rates where Region='NYSE All')
    when Region='Seoul' then Profit*(select Rate from dbo.rates where Region='Seoul')
    when Region='Taiwan' then Profit*(select Rate from dbo.rates where Region='Taiwan')
    when Region='Ukraine' then Profit*(select Rate from dbo.rates where Region='Ukraine')
    else ProfitUSD
    end

person Prateek Daniels    schedule 02.03.2015    source источник
comment
боже, это действительно неправильный способ выполнить это UPDATE. Прежде всего, вы получаете эту ошибку, потому что некоторые из этих (select Rate from dbo.rates where.....) возвращают более одной строки. Теперь вместо этого гигантского выражения CASE вы должны делать JOIN   -  person Lamak    schedule 02.03.2015
comment
У вас должен быть хотя бы один сценарий, в котором для региона используется более одной ставки. (Почему Region не уникален? Или, если он является частью другого уникального ключа, почему предложение не является более строгим?) Кроме того, тьфу. Думали ли вы об использовании объединения вместо этого отвратительного CASE выражения?   -  person Aaron Bertrand    schedule 02.03.2015


Ответы (2)


Ошибка означает, что один из ваших подзапросов (select rate from dbo.rates where region =) возвращает несколько значений. У вас есть две (или более) записи по крайней мере для одного из названий вашего региона в этой таблице.

Вы могли бы (должны) делать это обновление с помощью оператора JOIN вместо огромного оператора CASE; что происходит, когда вы добавляете новый регион?

update A set a.profitusd= a.profit*r.rate from dbo.[5 min] A join dbo.rates R on a.region = r.region 

Но это не решит проблему дубликатов в таблице rates.

person alroc    schedule 02.03.2015
comment
в таблице ставок нет дубликатов. в dbo.5mins есть повторяющиеся значения региона :) - person Prateek Daniels; 02.03.2015
comment
@PrateekDaniels Нет, в таблице dbo.Rates определенно есть дубликаты. - person Lamak; 02.03.2015

Это не решит вашу проблему, но использование update с join значительно упростит работу с запросом:

update f
    set ProfitUSD = Profit * coalesce(Rate, 1.0)
    from dbo.[5 Mins] f left join
         dbo.rates r
         on f.Region = r.Region;

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

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

select region, count(*)
from dbo.rates r
group by region
having count(*) > 1;

Затем исправьте данные. Или решите, какую строку вы хотите, и исправьте свою логику. В этой версии логику исправить будет намного проще.

person Gordon Linoff    schedule 02.03.2015