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

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
top n в подзапросе
    #36416466
amakhin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
LelikB,
А что значит последнее?
Код: plaintext
1.
2.
union all select  1 , '20090104',  2 
union all select  1 , '20090104',  5 
Вот у вас для одного параметра на одну дату два значения, какое из них последнее?
...
Рейтинг: 0 / 0
top n в подзапросе
    #36416526
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
top n в подзапросе
    #36416671
amakhin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
top n в подзапросе
    #36416914
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
top n в подзапросе
    #36417473
amakhin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
top n в подзапросе
    #36417859
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
top n в подзапросе
    #36418249
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
top n в подзапросе
    #36419078
LelikB
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
забыл пароль,
Возможно, изначально задача была сформулирована не самым лучшим образом.
Спасибо за варианты решения, общий смысл понятен.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / top n в подзапросе
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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