Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 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.065 c
15-1269207002
Юрий
2010-03-22 00:30
2010.08.27
С днем рождения ! 22 марта 2010 понедельник


15-1274957509
Kolan
2010-05-27 14:51
2010.08.27
Форма T-12


2-1274761583
Андрей_1
2010-05-25 08:26
2010.08.27
как перехватить сообщение


3-1237562794
SP
2009-03-20 18:26
2010.08.27
Коррелированный запрос UPDATE


15-1273955393
Юрий
2010-05-16 00:29
2010.08.27
С днем рождения ! 16 мая 2010 воскресенье





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский