Вниз
Скачать: CL | DM;

Запрос, MSSQL2000   Найти похожие ветки 

← →
Анна   (2010-04-29 09:04) [0]

Такая вот таблица:
id_ssd   n_oper    id_tool   catch_fish
1          1           17         155
1          2            0          45
1          3            0          44
1          4            3          88
1          5            0          123
5          1           41          9
5          2            0          77
5          3           33         100
5          4            0          44
5          5            0          78

Нужно  в запросе в id_tool  вместо нулей подставить предыдущее значение, которое <>0 для каждого id_ssd. В поле n_oper в первой операции (n_oper=1) id_tool всегда <>0. Значит если n_oper=2 и n_oper=3 имеют id_tool=0, то его надо "протащить" из 1-й операции. Если n_oper=4 имеет id_tool<>0, то  его надо "протащить" на 5-ую операцию.
Посоветуйте, пожалуйста, как сделать такой запрос.


← →
12 ©   (2010-04-29 09:21) [1]

если не большая табла - я б курсор пустил


← →
Анна   (2010-04-29 09:27) [2]


> 12 ©   (29.04.10 09:21) [1]

Это большая таблица. И этот  запрос мне нужно изменить в ХП, где с этой таблицой еще связаны 7. Пока я там не "протягиваю" - и  озвучиваю нули как "не определен." А по грамотному нужно "протянуть" и озвучить...Поэтому хотелось бы select-ом.


← →
Sergey13 ©   (2010-04-29 10:39) [3]

> [0] Анна   (29.04.10 09:04)

Не понял. Тебе нужно просто вывести "левые" данные или изменить их в таблице?


← →
Анна   (2010-04-29 10:51) [4]


> Sergey13 ©  

Вывести. Подставить в запросе вместо нулей.


← →
b z   (2010-04-29 10:52) [5]

case + подзапрос в случае 0


← →
b z   (2010-04-29 10:54) [6]

хотя гладя на данные не понятно для чего все это...


← →
Анна   (2010-04-29 11:06) [7]


> хотя гладя на данные не понятно для чего все это...

Чтобы красиво смотрелась выходная форма.


> b z   (29.04.10 10:52) [5]

Спасибо.


← →
Sergey13 ©   (2010-04-29 11:21) [8]

> [4] Анна   (29.04.10 10:51)

Можно попробовать подзапросом на каждую запись
Вот как то так примерно

select *,
(select id_tool
   from table_name t2
   where id_tool<>0
   and t1.id_ssd=t2.id_ssd
   and t1.n_oper>=(select max(n_oper) from table_name t3 where t2.id_ssd=t3.id_ssd)
)
from table_name t1


← →
b z   (2010-04-29 11:34) [9]


> Чтобы красиво смотрелась выходная форма.
А вы просто вкиньте туда семь, тоже очень красиво. :)


← →
Анна   (2010-04-29 13:54) [10]


> Sergey13 ©   (29.04.10 11:21) [8]

Спасибо!
Сделала так:
select t1.id_ssd,t1.n_op,t1.id_tool,"idttt"=
case when t1.id_tool=0 then
(select t2.id_tool
  from ssd_oper t2
 where t2.id_tool<>0
  and t1.id_ssd=t2.id_ssd
 and t2.n_op=(select max(n_op) from ssd_oper t3 where t2.id_ssd=t3.id_ssd
and t3.id_tool>0 and t3.n_op<t1.n_op)
)
when  t1.id_tool<>0 then t1.id_tool
end
from ssd_oper t1

> b z   (29.04.10 11:34) [9]

Я неправильно написала, не красиво, а чтобы понятнее было для прльзователя.


← →
sniknik ©   (2010-04-29 17:29) [11]

> Сделала так:
имхо, так будет лучше (если сонтаксис не попутал)
select t1.id_ssd,t1.n_op,t1.id_tool,"idttt"=
 case when t1.id_tool=0 then t1.id_tool
 else  
   case t1.n_oper=1 then 0
   else
     isNull(
     (select top 1 t2.id_tool from table_name t2 where t2.id_tool<>0 and t2.id_ssd=t1.id_ssd and t2.n_oper<t1.n_oper
order by t2.n_oper desc), 0)
   end
 end
from table_name t1


← →
Суслик_ ©   (2010-04-30 00:43) [12]

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

зависит от объема.
сколько строк?
если относительно много (допустим, миллионы), то я бы без подзапроса обошелся. все эти select top ... < order by desc тяжелые очень подзапросы.

в mssql есть такая классная и вроде как недокументированная (или документированная - не помню) особенность - можно пробежаться по таблице по кластерному индексу (или просто по индексу, тоже не помню).

делается примерно так.
update t
set
...
from #TempTable t with (index(0))


, где нулевой индекс - это индекс по полям, по которым идет упорядочивание.

а далее - уже простой цикл ))) типа while.
надо запоминать в локальных переменных требуемые прошлые значения

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

PPS. подход рабочий - используется у нас для построения отчетности по объектам с глубокой историчностью и большим количеством фактов в жизни объекта. там подзапросы точно не идут.


← →
Суслик_ ©   (2010-04-30 01:01) [13]

немного не так сказал:  index(0) - это первый созданный для таблицы индекс.


← →
sniknik ©   (2010-04-30 01:32) [14]

> то я бы без подзапроса обошелся. все эти select top ... < order by desc тяжелые очень подзапросы.
я бы тоже, но альтернативой бы выбрал курсор... против которого тут выражались, что нужен запрос...

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


← →
Суслик_ ©   (2010-04-30 01:40) [15]

у меня есть блок учета ОС (основные средства).
вот эти гады имеют особенность иметь до фига исторических данных.
самый простой пример - каждый месяц идет амортизация )) все бы ничего, но в общем случае каждый месяц может менять база амортизации и т.д.

а нужно узнать амортизацию, которая была накоплена, когда ОС находится в таком-то депо (у нас вагоны).

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

я долго бился, но лучший вариант:
1. загнать во временную таблицу известные факты из жизни ОС.
2. пробежаться по ней обозначенным выше способом, расчитав недостающие факты из жизни ОС.
3. по временной таблице построить нужный отчет.


← →
Анна   (2010-04-30 10:58) [16]

sniknik ©   (29.04.10 17:29) [11]

Ваш запрос немного исправила :

select t1.id_ssd,t1.n_op,t1.id_tool,"idttt"=
case when t1.id_tool<>0 then t1.id_tool
else  
  case when t1.n_op=1 then 0
  else
    isNull(
    (select top 1 t2.id_tool from ssd_oper t2 where t2.id_tool<>0
     and t2.id_ssd=t1.id_ssd and t2.n_op<t1.n_op
     order by t2.n_op desc), 0)
  end
end
from ssd_oper t1
order by 1

Работает немного быстрее, чем мой. 730тыс записей отбирает за 5 сек. Мой за 6 сек.
Спасибо, за ваши "элегантные" запросы.


← →
Sergey13 ©   (2010-04-30 11:10) [17]

> [16] Анна   (30.04.10 10:58)
> 730тыс записей отбирает

> Чтобы красиво смотрелась выходная форма.

Лепота! (с)И.В.Грозный.
8-)


← →
Анна   (2010-04-30 11:13) [18]


> Sergey13 ©   (30.04.10 11:10) [17]

Во-первых, я просто проверяла скорость выполнения двух запросов. По-моему д.б. понятно  :))
Естественно, в выходных формах не тот объем, ограничение по времени и др...


← →
sniknik ©   (2010-04-30 11:17) [19]

> Работает немного быстрее, чем мой
попробуй с курсором, должно быть быстрее т.к. будет "однопроходный".


← →
Анна   (2010-04-30 11:20) [20]


> sniknik ©   (30.04.10 11:17) [19]

Попробую.Простото никогда не писала с курсором, поэтому надо почитать про это.


← →
Анна   (2010-04-30 13:08) [21]


> sniknik ©   (30.04.10 11:17) [19]

И ваш заапрос правильнее построен чем мой. Т.к. в старых записях за прошлые годы, встречаются записи, где id_tool=0 во всех операциях и "протягивать" нечего для данной id_ssd. Ваш запрос такие записи извлекает, а мой нет :((


← →
b z   (2010-04-30 16:00) [22]

Надо базу сменить. А подзапрос замениить на семь. Скорость будет великолепная.



Страницы: 1 вся ветка

Скачать: CL | DM;



Память: 0.51 MB
Время: 0.047 c
15-1268248494
кот
2010-03-10 22:14
2010.08.27
как прочитать ПЗУ через параллельный порт


2-1267710669
Евгений Р.
2010-03-04 16:51
2010.08.27
Использование tOpenDialog


15-1264800605
Юрий
2010-01-30 00:30
2010.08.27
С днем рождения ! 30 января 2010 суббота


15-1274747389
Юрий
2010-05-25 04:29
2010.08.27
С днем рождения ! 25 мая 2010 вторник


15-1273436998
Юрий
2010-05-10 00:29
2010.08.27
С днем рождения ! 10 мая 2010 понедельник




   Наверх