Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / top n в подзапросе / 9 сообщений из 9, страница 1 из 1
18.01.2010, 16:50
    #36416390
LelikB
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
top n в подзапросе
Добрый день!

Sybase ASE/12.5.4

Дано: две таблицы. В одной (#a1) перечислены сущности, в другой (#a2) - значение какого-либо параметра для каждой сущности на дату.

Необходимо определить последнее значение параметра для каждой сущности.

Как это сделать в Sybase без использования TOP n в подзапросах?

Тестовые данные:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
create table #a1
( 
 id int
)

create table #a2
(
  a1_id    int
 ,date     smalldatetime
 ,a2_value int
)

insert  #a1 

select  1 
union all select  3 
union all select  4 
union all select  5 
union all select  6 


insert #a2
          select  1 , '20090101',  2 
union all select  1 , '20090102',  1 
union all select  1 , '20090103',  2 
union all select  1 , '20090104',  2 
union all select  1 , '20090104',  5 
union all select  2 , '20090103',  5 
union all select  5 , '20090103',  5 
union all select  6 , '20090103',  5 

...
Рейтинг: 0 / 0
18.01.2010, 17:24
    #36416466
amakhin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
top n в подзапросе
LelikB,
А что значит последнее?
Код: plaintext
1.
2.
union all select  1 , '20090104',  2 
union all select  1 , '20090104',  5 
Вот у вас для одного параметра на одну дату два значения, какое из них последнее?
...
Рейтинг: 0 / 0
18.01.2010, 17:43
    #36416526
LelikB
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
top n в подзапросе
amakhin,

Предположим, что в таблице #a2 есть идентификатор, т.е. если на дату задано два параметра, то нужно брать параметр с максимальным ID.

Код: plaintext
1.
2.
3.
4.
5.
6.
create table #a2
(
  id         int  identity 
  a1_id    int
 ,date     smalldatetime
 ,a2_value int
)

В MSSQL такая задача может быть решена примерно так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
select	 a1.id
		,(	select top  1  a2.a2_value
			from #a2 a2
			where a2.a1_id = a1.id
			and a2.date < '20090104'
			order by a2.date desc, id desc
			
		)
from #a1 a1
...
Рейтинг: 0 / 0
18.01.2010, 18:49
    #36416671
amakhin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
top n в подзапросе
LelikB,

Код: plaintext
1.
2.
3.
4.
5.
select a1."id", a22.a2_value from #a1 a1
left outer join 
(select max(a2."id") as id , max("date") as "date", a1_id from #a2 a2
group by a1_id) as t ON a1."id" = t.a1_id
left outer join #a2 a22 ON a22."id" = t."id"

вот такое получилось. Может можно и изящнее.
...
Рейтинг: 0 / 0
18.01.2010, 22:19
    #36416914
LelikB
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
top n в подзапросе
amakhin,

Увы, такой способ не подходит в случае, если нужно выбрать значение с максимальной датой и минимальным ID.

Т.е., например, нужно найти значение с максимальной датой. Если на дату задано несколько значений, то нужно выбрать значение с минимальным ID.

Для MSSQL достаточно изменить вариант сортировки по ID:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
select	 a1.id
		,(	select top  1  a2.a2_value
			from #a2 a2
			where a2.a1_id = a1.id
			and a2.date < '20090104'
			order by a2.date desc, id asc
			
		)
from #a1 a1

Хотелось бы найти вариант покрасивее, чем этот:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
select a1.id, a23.a2_value
from #a1 a1
 left outer join 
(
select a22.a1_id, a22.date, min(a22.id) as id
from #a2 a22
 inner join 
(
select a2.a1_id as a1_id, max(date) as date
from #a2 a2
where date < '20090104'
group by a2.a1_id 
) t1
 on  a22.a1_id = t1.a1_id
 and a22.date = t1.date
group by a22.a1_id, a22.date
) t22
on a1.id = t22.a1_id
 left outer join #a2 a23
  on t22.id = a23.id
...
Рейтинг: 0 / 0
19.01.2010, 11:13
    #36417473
amakhin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
top n в подзапросе
LelikB,
а что мешает сделать так
Код: plaintext
1.
2.
3.
4.
5.
select a1."id", a22.a2_value from #a1 a1
left outer join 
(select min(a2."id") as id , max("date") as "date", a1_id from #a2 a2
group by a1_id) as t ON a1."id" = t.a1_id
left outer join #a2 a22 ON a22."id" = t."id"
...
Рейтинг: 0 / 0
19.01.2010, 13:06
    #36417859
LelikB
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
top n в подзапросе
amakhin,

Это не совсем корректный вариант.
Посмотрите на тестовые данные: для a1_id=1 за 20090104 есть два значения: 2 и 5. Мне нужно взять значение с минимальным id, т.е. 2.
Однако Ваш запрос для a1_id=1 возьмет min(id), соответствующий 20090101.

Это будет наглядно видно, если изменить тестовые данные за '20090101', например, таким образом:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
insert #a2
          select  1 , '20090101',  1 
union all select  1 , '20090102',  1 
union all select  1 , '20090103',  2 
union all select  1 , '20090104',  2 
union all select  1 , '20090104',  5 
union all select  2 , '20090103',  5 
union all select  5 , '20090103',  5 
union all select  6 , '20090103',  5 
...
Рейтинг: 0 / 0
19.01.2010, 15:03
    #36418249
top n в подзапросе
LelikB,

Вы бы задачу описали нормально. Есть id, которого в данных нет (предполагайте сами), потом нужно определить последнее значение параметра, а потом нужно оказывается брать минимальное id.

create table #a2
( id int,
a1_id int,
dt smalldatetime,
a2_value int)
go

insert #a2
select 1,1, '20090101', 1
union all select 2,1, '20090102', 1
union all select 3,1, '20090103', 2
union all select 4,1, '20090104', 2
union all select 5,1, '20090104', 5
union all select 6,2, '20090103', 5
union all select 7,5, '20090103', 5
union all select 8,6, '20090103', 5
go

select a1_id, min_id, max_id, (select a2_value from #a2 where id=TT.min_id) as first_value, (select a2_value from #a2 where id=TT.max_id) as last_value, convert(varchar,dt,102)
FROM (
select a1_id, dt, min(id) as min_id, max(id) as max_id
from #a2 t1
where dt=(select max(dt) from #a2 where a1_id=t1.a1_id)
group by a1_id, dt
) TT
order by 1
go
...
Рейтинг: 0 / 0
19.01.2010, 20:36
    #36419078
LelikB
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
top n в подзапросе
забыл пароль,
Возможно, изначально задача была сформулирована не самым лучшим образом.
Спасибо за варианты решения, общий смысл понятен.
...
Рейтинг: 0 / 0
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / top n в подзапросе / 9 сообщений из 9, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]