powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / Агрегирование агрегированного
10 сообщений из 10, страница 1 из 1
Агрегирование агрегированного
    #36408709
Фотография Ex_Soft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попалось на глаза: вывести TOP-10 товара, количество которого больше всего. Родил
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT
   T1.ID,
   sum(T1.CNT)
FROM
   TOV T1
GROUP BY
   T1.ID
HAVING
   sum(T1.CNT) IN
   (SELECT DISTINCT top  10  sum(T2.CNT) FROM TOV T2 GROUP BY T2.ID ORDER BY  1  DESC)
но
select @@version
Adaptive Server Enterprise/15.0.2/EBF 14332/P/NT (IX86)/Windows 2000/ase1502/2486/32-bit/OPT/Thu May 24 04:10:36 2007

такое (а именно: top && order by в подзапросе) - не осилил (впрочем, как и MySQL 5.1.41). А, вот, FB-2.1.3.18185
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT
   T1.ID,
   sum(T1.CNT)
FROM
   TOV T1
GROUP BY
   T1.ID
HAVING
   sum(T1.CNT) IN
   (SELECT first  10  DISTINCT sum(T2.CNT) FROM TOV T2 GROUP BY T2.ID ORDER BY  1  DESC)
Выдал на гора правильно. Но как-то, IMHO, ректально это. Во-первых: исходя из самой постановки, я так понял, предполагается традиционный SQL (без first / top / limit ). А, во-вторых, если бы не было суммирования - то сие выливается в простой запросец с подзапросом. Все еще теплится надежда, что и этот можно организовать попроще. Как?
_________________
"Helo, word!" - 17 errors 56 warnings
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Агрегирование агрегированного
    #36408774
А тем обычные TOP N запросы не устроили?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
/* MySQL*/
SELECT
   T1.ID,
   sum(T1.CNT)
FROM
   TOV T1
GROUP BY
   T1.ID
ORDER BY sum(T1.CNT) desc
limit  10 ;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
/* MS SQL Server/SyBase ASE */
SELECT top  10 
   T1.ID,
   sum(T1.CNT)
FROM
   TOV T1
GROUP BY
   T1.ID
ORDER BY sum(T1.CNT) desc;


В принципе, можно и на "голом" ANSI-SQL реализовать, без всяких там серверозависимых конструкций.
...
Рейтинг: 0 / 0
Агрегирование агрегированного
    #36408794
Фотография Ex_Soft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый Э - Эх
А тем обычные TOP N запросы не устроили?

Поясню на пальцах. Допустим, у Вас на складе:
Id Name Cnt1 Игрушка "Дед Мороз" 3002 Ель живая 3003 Гирлянда елочная 50
И Вам необходимо выбрать TOP(1). TOP(1)=300. Соответственно в результате выборки Вы должны получить:
Id Name Cnt1 Игрушка "Дед Мороз" 3002 Ель живая 300
т.е. - 2-ве записи. В Вашем же варианте Вы получите только одну запись, к примеру:
Id Name Cnt1 Игрушка "Дед Мороз" 300
Вроде - мелочь. Но если Вы дадите такой ответ по состоянию на 31-е декабря, то 1-го января Вас заставят выкупить все, не попавшие в выборку, и, как следствие, - нереализованные 300 елочек прямо со склада.
Добрый Э - Эх
В принципе, можно и на "голом" ANSI-SQL реализовать, без всяких там серверозависимых конструкций.

Вот за что и боремся ж то...
_________________
"Helo, word!" - 17 errors 56 warnings
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Агрегирование агрегированного
    #36408804
Mikle83
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А все обязательно необходимо сделать в рамках одного запроса?
А если разделить? Сначала определить топ-10 "максимальных количеств", а вторым запросом выбрать все записи с таким количеством (как вариант - через временную таблицу)?
...
Рейтинг: 0 / 0
Агрегирование агрегированного
    #36408818
Ex_Soft , всё что нужно - перенести подзапрос из секции HAVING в секцию JOIN.
Уж декартово произведение таблиц все сервера поддерживают, группировку тоже. Поэтому не вижу никаких сложностей написать запрос в виде:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
select t.id, t.name, sum(t.cnt) as sum_cnt,
       max(v1.max_sum_cnt)
  from t
  cross join 
        (
          select max(sum_cnt) as max_sum_cnt
            from (
                   select sum(cnt) as sum_cnt
                     from t
                    group by id
                 ) v0
        ) v1
 group by t.id, t.name
having max(v1.max_sum_cnt) = sum(t.cnt)
 order by t.id
...
Рейтинг: 0 / 0
Агрегирование агрегированного
    #36408833
Причем, для произвольного N запрос "TOP N " будет иметь немного другой вид:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
select t1.id, t1.name, t1.cnt
  from tov t1
  join tov t2
    on t1.cnt <= t2.cnt
   and t1.id != t2.id 
 group by t1.id, t1.name, t1.cnt
having count(distinct t2.id) <= :N
 order by count(distinct t2.id), id
, где - вместо :N нужно подставить интересуемое значение.
...
Рейтинг: 0 / 0
Агрегирование агрегированного
    #36408837
Пардон, в предыдущем сообщении небольшая недоработка.
Вот так оно должно быть правильнее:
Код: plaintext
1.
2.
3.
4.
5.
6.
select t1.id, t1.name, t1.cnt
  from tov t1
  join tov t2
    on t1.cnt <= t2.cnt
 group by t1.id, t1.name, t1.cnt
having count(distinct t2.cnt) <= :N
order by count(distinct t2.id), id
...
Рейтинг: 0 / 0
Агрегирование агрегированного
    #36409312
Фотография Ex_Soft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый Э - Эх
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
select  t1.id, t1.name, t1.cnt
    from  tov t1
    join  tov t2
      on  t1.cnt<= t2.cnt
   group  by  t1.id, t1.name, t1.cnt
having  count(distinct  t2.cnt)<= :N
order  by  count(distinct  t2.id), id

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
create table TOV
(
    ID int not null,
    CNT int
)
go

insert into TOV (ID, CNT) values ( 1 ,  10 )
insert into TOV (ID, CNT) values ( 2 ,  200 )
insert into TOV (ID, CNT) values ( 3 ,  3000 )
insert into TOV (ID, CNT) values ( 1 ,  20 )
insert into TOV (ID, CNT) values ( 2 ,  400 )
insert into TOV (ID, CNT) values ( 3 ,  6000 )
insert into TOV (ID, CNT) values ( 4 ,  5000 )
insert into TOV (ID, CNT) values ( 5 ,  110 )
insert into TOV (ID, CNT) values ( 2 ,  4400 )
go
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
select
   T1.ID,
   sum(T1.CNT) as CNT
from
   TOV T1
group by
   T1.ID
order by  2  desc
IDCNT3900025000450005110130
Отсюда:
TOP-1
IDCNT39000
TOP-2
IDCNT390002500045000
TOP-3
IDCNT3900025000450005110
_________________
"Helo, word!" - 17 errors 56 warnings
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Агрегирование агрегированного
    #36409424
Ex_Soft
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
create table TOV
(
    ID int not null,
    CNT int
)

insert into TOV (ID, CNT) values ( 1 ,  10 )
insert into TOV (ID, CNT) values ( 2 ,  200 )
insert into TOV (ID, CNT) values ( 3 ,  3000 )
insert into TOV (ID, CNT) values ( 1 ,  20 )
insert into TOV (ID, CNT) values ( 2 ,  400 )
insert into TOV (ID, CNT) values ( 3 ,  6000 )
insert into TOV (ID, CNT) values ( 4 ,  5000 )
insert into TOV (ID, CNT) values ( 5 ,  110 )
insert into TOV (ID, CNT) values ( 2 ,  4400 )


И какие сложности?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
select  t1.id, t1.cnt
    from  (select id, sum(cnt) as cnt from tov group by id) t1
    join  (select id, sum(cnt) as cnt from tov group by id) t2
      on  t1.cnt<= t2.cnt
   group  by  t1.id, t1.cnt
having  count(distinct  t2.cnt)<= :N
order  by  count(distinct  t2.id), id

Оно, конечно, тоже из "ректальной медицины", но зато на "чистом ANSI", будь он неладен...
...
Рейтинг: 0 / 0
Агрегирование агрегированного
    #36409592
Фотография Ex_Soft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый Э - Эх,

_________________
"Helo, word!" - 17 errors 56 warnings
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / Агрегирование агрегированного
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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