Форум: "Прочее";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
ВнизЗапрос, 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 вся ветка
Форум: "Прочее";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.075 c