Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите с case в колонках запроса основанного на подзапросе  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
select  case us_price when 1 then (select source_price  where us_price = 1 and source_price is not NULL) end

	
from (
select TOP 2 MIN(source_price) as source_price , us_price, target_price   from (
select  15 as source_price,
		0 as us_price ,	
		NULL as target_price,	
		100 as source_quantity,		
		40 as targer_quantity				
UNION 
select  25 ,		0,	NULL,	10,	40	
UNION  
select  35 ,		0,	NULL,	1,		40	
UNION
select  0.15 ,		1,	NULL,	100,	40	
UNION 
select  0.28 ,	1,	NULL,	10,	40	
UNION  
select  0.45 ,	1,	NULL,	1,		40	
) a
group by us_price, target_price
) b

Есть сложный запрос который будет использоваться для UPDATE
Проблема вот в чём. Если убрать верхний подзапрос то есть сделать так
select TOP 2 MIN(source_price) as source_price , us_price, target_price   from (
select  15 as source_price,
		0 as us_price ,	
		NULL as target_price,	
		100 as source_quantity,		
		40 as targer_quantity				
UNION 
select  25 ,		0,	NULL,	10,	40	
UNION  
select  35 ,		0,	NULL,	1,		40	
UNION
select  0.15 ,		1,	NULL,	100,	40	
UNION 
select  0.28 ,	1,	NULL,	10,	40	
UNION  
select  0.45 ,	1,	NULL,	1,		40	
) a
group by us_price, target_price

то вывод будет такой
source_price us_price target_price
15.00 0 NULL
0.15 1 NULL

И теперь я хочу из этого вывода select where в case
То есть я думал если я напишу SELECT b.source_price where us_price = 0
то вывод будет
source_price
15.00


Но вместо этого я получаю
NULL
0.15

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

В конце концов я бы хотел бы видеть что-то вроде этого
UPDATE tblSalesProducts 
	SET Amount = case us_price  when 1 then (select source_price where us_price = 1 and source_price is not NULL) end,
		SalePrice = case us_price  when 0 then  (select source_price where us_price = 0 and b.target_price IS NULL) end
from (
select TOP 2 MIN(source_price) as source_price , us_price, target_price   from (
select  15 as source_price,
		0 as us_price ,	
		NULL as target_price,	
		100 as source_quantity,		
		40 as targer_quantity				
UNION 
select  25 ,		0,	NULL,	10,	40	
UNION  
select  35 ,		0,	NULL,	1,		40	
UNION
select  0.15 ,		1,	NULL,	100,	40	
UNION 
select  0.28 ,	1,	NULL,	10,	40	
UNION  
select  0.45 ,	1,	NULL,	1,		40	
) a
group by us_price, target_price
) b

но из-за этой проблемы я получаю на выход две строки вместо одной и в SET идёт не то значение
13 авг 16, 12:33    [19536903]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с case в колонках запроса основанного на подзапросе  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
Kimel,

В общем эту проблему решил таким образом.
Весь результат селекта занёс в табличную переменную и дальше работал с ней и этот баг исчез.
13 авг 16, 19:24    [19537344]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с case в колонках запроса основанного на подзапросе  [new]
iljy
Member

Откуда:
Сообщений: 8711
Kimel,

а с какого перепугу это баг-то? У вас во вложенном select нет никакой таблицы, так что все поля берутся из текущей строки. Конкретно ваш
select source_price  where us_price = 1 and source_price is not NULL


в данном контексте эквивалентен

case when us_price = 1 and source_price is not NULL then source_price  end


Если брать во вложенном select выборку из табличной переменной, то естественно результат будет другим.
13 авг 16, 22:52    [19538003]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с case в колонках запроса основанного на подзапросе  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
iljy,

Я всё понимаю, я не правильно выразился, но другого решения проблемы я не нашел к сожалению
14 авг 16, 00:05    [19538236]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с case в колонках запроса основанного на подзапросе  [new]
iljy
Member

Откуда:
Сообщений: 8711
Kimel,

а проблема-то, собственно, в чем? Что сделать надо?
14 авг 16, 02:48    [19538519]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с case в колонках запроса основанного на подзапросе  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31912
Kimel
Я просидел всю ночь из-за этой маленькой проблемы и не смог понять почему так происходит.
CASE - это скалярная функция.
Для каждой строки вычисляется выражение после SET Amount = <тут скалярное выражение>, и неважно, в этом выражении будет CASE, или ещё какие то функции и операторы.
То есть для стейтмента UPDATE tblSalesProducts берутся строки в таблице tblSalesProducts (т.к. нет условия, то берутся все строки), и в каждой строке устанавливается новое значение для полей Amount и SalePrice.
Оно как то там вычисляется, там +, =, CASE, и т.д., но установлено будет для всех строк.

Далее, подзапрос "from (..." возвращает 2 строки.
Условия связывания нет, т.е. для обновляемой строки в tblSalesProducts берётся, грубо говоря, произвольная строка в подзапросе.

И вот для этого сочетания (поля из строки в tblSalesProducts и поля из этой строки подзапроса) вычисляются скалярные значения для установки значения SET для обновления.

Для выбора правильной строки из подзапроса вам нужно переписать этот UPDATE на форму FROM - JOIN, и перенести условие из CASE в условие джойна.
А так как обновляемых поля 2, то нужно подзапрос сделать в виде CTE, и сджойнить его 2 раза с обновляемой таблицей, с разными условиями.

Типа того:
;WITH b(
	select TOP 2 MIN(source_price) as source_price , us_price, target_price   
	from (
		select  15 as source_price,
			0 as us_price ,	
			NULL as target_price,	
			100 as source_quantity,		
			40 as targer_quantity				
		UNION 
		select  25 ,		0,	NULL,	10,	40	
		UNION  
		select  35 ,		0,	NULL,	1,		40	
		UNION
		select  0.15 ,		1,	NULL,	100,	40	
		UNION 
		select  0.28 ,	1,	NULL,	10,	40	
		UNION  
		select  0.45 ,	1,	NULL,	1,		40	
	) a
	group by us_price, target_price
)
UPDATE s
	SET	Amount = b1.source_price
		SalePrice = b2.source_price
from tblSalesProducts s
    join b as b1 on b1.us_price = 1 and b1.source_price is not NULL
    join b as b2 on b1.us_price = 0 and b1.source_price is NULL
14 авг 16, 13:07    [19538823]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с case в колонках запроса основанного на подзапросе  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31912
alexeyvg
from tblSalesProducts s
    join b as b1 on b1.us_price = 1 and b1.source_price is not NULL
    join b as b2 on b1.us_price = 0 and b1.source_price is NULL

То есть так:
from tblSalesProducts s
    join b as b1 on b1.us_price = 1 and b1.source_price is not NULL
    join b as b2 on b2.us_price = 0 and b2.source_price is NULL

В общем, примерно так.
14 авг 16, 13:09    [19538824]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с case в колонках запроса основанного на подзапросе  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34697
Kimel
Kimel,

В общем эту проблему решил таким образом.
Весь результат селекта занёс в табличную переменную и дальше работал с ней и этот баг исчез.

это не баг, это твое незнание SQL...
14 авг 16, 16:45    [19539149]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с case в колонках запроса основанного на подзапросе  [new]
Kimel
Member

Откуда: Украина
Сообщений: 334
alexeyvg,

Спасибо, вы всё правильно подсказали.
Но к сожалению в этом запросе есть фундаментальные ошибки, которые я не заметил, наверное из-за усталости, поэтому он не годен.
Я имею ввиду в самом первом select.

Я всё перепишу заново, но ваше решение работает и это то, что я хотел, поэтому большое вам спасибо.
14 авг 16, 21:37    [19539812]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить