Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Составление SQL-запросов > SQL-запрос


Автор: kvadrokub 18.10.2010, 08:10
Всем доброго времени суток. На экзамене по БД попался такой вопрос с написанием SQL-запроса:

Имеется таблица:
++++++++++++++++++++++++++++
|     id     | Номер команды | Результат |
++++++++++++++++++++++++++++
|     1      |           10            |     1000     |
|     2      |           12            |     1100     |
|     3      |           10            |      500      |
|     4      |           11            |      700      |
|    ...      |           ...             |        ...       |
++++++++++++++++++++++++++++
Найти номер команды, которая больше всего раз встречается в таблице.

Вот примерно так выглядит условие. Помогите, пожалуйста.

Автор: Akina 18.10.2010, 08:24
Код

select top 1 num_c
from table
group by num_c
order by count(num_c) desc
Однако не определено, что делать, если команд с таким количеством несколько.

Автор: kvadrokub 18.10.2010, 08:26
top 1 - это, получается, одно самое большое значение?

Автор: Akina 18.10.2010, 08:30
При указанной сортировке - да. Есссно это диалектозависимо - например в MySQL это будет LIMIT 1.

Автор: kvadrokub 18.10.2010, 08:33
Цитата(Akina @ 18.10.2010,  10:30)
При указанной сортировке - да. Есссно это диалектозависимо - например в MySQL это будет LIMIT 1.

Тогда немного конкретизирую задачу. Написать без top 1, а с помощью подзапросов. Также, чтобы не было диалектозависимо, а было на чистом SQL.

Автор: Данкинг 18.10.2010, 09:09
Цитата(kvadrokub @  18.10.2010,  09:33 Найти цитируемый пост)
Также, чтобы не было диалектозависимо, а было на чистом SQL. 

Это как так, интересно? Тебе Akina пример запроса привёл, а далее говоришь преподу, что частный случай зависит от конкретной СУБД. smile 

Автор: kvadrokub 18.10.2010, 09:14
Цитата(Данкинг @ 18.10.2010,  11:09)
Цитата(kvadrokub @  18.10.2010,  09:33 Найти цитируемый пост)
Также, чтобы не было диалектозависимо, а было на чистом SQL. 

Это как так, интересно? Тебе Akina пример запроса привёл, а далее говоришь преподу, что частный случай зависит от конкретной СУБД. smile

Нужно как раз-таки написать так, чтобы запрос работал на любой СУБД одинаково и не нужно было ничего менять, т.е. на голом ANSI SQL. Ну, например, только с использованием max и count.

Автор: Zloxa 18.10.2010, 09:42
Цитата(kvadrokub @  18.10.2010,  09:14 Найти цитируемый пост)
 т.е. на голом ANSI SQL.

SQL92
Код

select command from table group by commmand having count(*)  = (select max(count(*)) from table group by command)

Вернет ВСЕ команды, повторяющиеся наиболшьшее количество раз.
может статься, что этот запрос вполне соответствует и SQL86

SQL2003
Код

select command from (select command, row_number over (order by count(*) desc) rn from table group by command) s where rn = 1 

Вернет любую одну команду, повторяющуюся наибольшее количество раз
Если нужно чтобы были выведены все команды, повторяющиеся наибольшее количество раз, row_number заменить на dence_rank

Добавлено @ 09:46
следует отметить что SQL2003 держут отнюдь не все движки. Ровно как и SQL92

Автор: Akina 18.10.2010, 10:01
Код

select q.num_c
from
(
  select t.num_c, count(t.num_c) as cnt_num_c
  from table as t
  group by t.num_c
) as q
group by q.num_c
having q.cnt_num_c=max(q.cnt_num_c)
Вернёт все записи, у которых количество равно максимальному.

Автор: kvadrokub 18.10.2010, 10:02
Вау, супер!  smile  Пошёл пробовать. smile

А у меня первоначальный вариант был примерно такой:

SELECT TEAM
FROM TABLE,
          (SELECT TEAM, COUNT(TEAM) AS CNT
           FROM TABLE
           GROUP BY TEAM) A
WHERE TABLE.TEAM = A.TEAM AND (SELECT MAX(CNT) FROM A) = и вот тут ступор smile

Автор: Zloxa 18.10.2010, 10:05
Цитата(Akina @  18.10.2010,  10:01 Найти цитируемый пост)

group by q.num_c
having q.num_c=max(q.num_c)

предикат вернет истину для каждой строки.

Автор: kvadrokub 18.10.2010, 10:36
Кстати говоря, никто из вас не умеет правильно писать запросы. smile Zloxa не дружит с GROUP BY совершенно, а у Akina просто неправильные запросы. ;) Не сдали бы вы экзамен в моём университете. smile

Автор: Zloxa 18.10.2010, 10:39
Цитата(kvadrokub @  18.10.2010,  10:36 Найти цитируемый пост)
Кстати говоря, Zloxa, ты не умеешь правильно писать GROUP BY.

ты не мог бы намекнуть менее прозрачно?

Автор: kvadrokub 18.10.2010, 10:41
Цитата(Zloxa @ 18.10.2010,  12:39)
Цитата(kvadrokub @  18.10.2010,  10:36 Найти цитируемый пост)
Кстати говоря, Zloxa, ты не умеешь правильно писать GROUP BY.

ты не мог бы намекнуть менее прозрачно?

Я про этот запрос:
select command from table group by commmand having count(*)  = (select max(count(*)) from table group by command)

Автор: Zloxa 18.10.2010, 10:42
Цитата(kvadrokub @  18.10.2010,  10:41 Найти цитируемый пост)
Я про этот запрос:

Иииииии?

Автор: Akina 18.10.2010, 10:43
Цитата(kvadrokub @  18.10.2010,  11:36 Найти цитируемый пост)
Zloxa не дружит с GROUP BY совершенно, а у Akina просто неправильные запросы

 smile Спасибо, поржал! 

Автор: kvadrokub 18.10.2010, 10:44
Цитата(Zloxa @ 18.10.2010,  12:42)
Цитата(kvadrokub @  18.10.2010,  10:41 Найти цитируемый пост)
Я про этот запрос:

Иииииии?

http://www.sql-tutorial.ru/ru/book_group_by_clause.html

Автор: Zloxa 18.10.2010, 10:45
Цитата(kvadrokub @  18.10.2010,  10:44 Найти цитируемый пост)
http://www

И все же... Иииииии?

Автор: kvadrokub 18.10.2010, 10:46
Цитата(Zloxa @ 18.10.2010,  12:45)
Цитата(kvadrokub @  18.10.2010,  10:44 Найти цитируемый пост)
http://www

И все же... Иииииии?

Ну создай таблицу, запусти и попробуй.

Автор: Zloxa 18.10.2010, 10:49
Цитата(kvadrokub @  18.10.2010,  10:46 Найти цитируемый пост)
Ну создай таблицу, запусти и попробуй. 

Мне то это зачем? 
Я знаю где ошибся, но к сути вопроса это отношения не имеет.

Хотя да, ты прав. Я ступил. Надо было тебе посоветовать взять букрварь по SQL и почитать его.

Автор: kvadrokub 18.10.2010, 10:56
Вот это твой запрос:
select command 
from table 
group by commmand 
having count(*)  = (select max(count(*)) 
                               from table 
                               group by command)

Буду разбирать по косточкам.
Возьму для начала вложенный подзапрос:
select max(count(*)) 
from table 
group by command

Во-первых, нельзя писать max(count(*)). Во-вторых, правильно будет выглядеть так:  
select command, count() или max() - одно из двух
from table 
group by command

, т.е. ошибка в написании GROUP BY. Его нельзя использовать так, как ты там писал.
Третяя ошибка вглавном запросе, там также в первой строке нужно использовать агрегатную функцию, иначе опять-таки GROUP BY выдаст ошибку.
Ну и в четвёртых, исходя из всех этих ошибок весь запрос неверен.
Проверял на MySQL, знаю по Oracle.
Ну и команда по-английски team, а не command, хотя это не важно, в принципе.

Я же говорю, создайте и попробуйте сами, если не верите мне.

Автор: Frees 18.10.2010, 11:07
kvadrokub, а вопрос то у тебя какой, или ты возмущен что тебе дали не вылизанный запрос?
Ты сам думай как делать направление тебе дали, включи голову и не бухти..

Автор: Zloxa 18.10.2010, 11:09
Цитата(kvadrokub @  18.10.2010,  10:56 Найти цитируемый пост)
Во-первых, нельзя писать max(count(*))

кто сказал?
Цитата(kvadrokub @  18.10.2010,  10:56 Найти цитируемый пост)
там также в первой строке нужно использовать агрегатную функцию

вовсе нет, группировка не обязывает к использованию аггрегатов
Цитата(kvadrokub @  18.10.2010,  10:56 Найти цитируемый пост)
Ну и команда по-английски team, а не command, хотя это не важно, в принципе

слово "команда" имеет несколько смылов в русском языке, в лишь одном из них, не самом употребмимом, на английский она переводится как http://lingvo.yandex.ru/%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0/%D0%BF%D0%BE-%D0%B0%D0%BD%D0%B3%D0%BB%D0%B8%D0%B9%D1%81%D0%BA%D0%B8/
Цитата(kvadrokub @  18.10.2010,  10:56 Найти цитируемый пост)
знаю по Oracle.

Цитата(kvadrokub @  18.10.2010,  10:56 Найти цитируемый пост)
попробуйте сами,

уболтал ;)
Код

Connected to Oracle9i Enterprise Edition Release 9.2.0.8.0 

SQL> with t  as (select 1 command from dual
  2              union all select 2 command from dual
  3              union all select 2 command from dual
  4              union all select 2 command from dual)
  5  select command from t group by command having count(*) = (select max(count(*)) from t group by command)
  6  ;
 
   COMMAND
----------
         2



Цитата(kvadrokub @  18.10.2010,  10:56 Найти цитируемый пост)
Ну и в четвёртых, исходя из всех этих ошибок весь запрос неверен.

молодец! Развеселил. Такой милый троллинг smile

Автор: kvadrokub 18.10.2010, 11:43
С тем, что не обязательно использовать агрегатную функцию с GROUP BY соглашусь, но вот MAX(COUNT(*)), по крайней мере в MySQL (Oracle недавно снёс и не могу проверить), нельзя писать: http://file.qip.ru/photo/_CxZwRKZ/sql.html? 

Автор: Zloxa 18.10.2010, 12:00
Цитата(kvadrokub @  18.10.2010,  11:43 Найти цитируемый пост)
в MySQL нельзя писать

оберни в подзапрос
Код

select max(cnt) from (select count(*) cnt from table group by command) s


Автор: kvadrokub 18.10.2010, 12:06
Уже. Спасибо за помощь, извини за нападки. smile

Автор: Zloxa 18.10.2010, 12:31
Цитата(kvadrokub @  18.10.2010,  12:06 Найти цитируемый пост)
 Спасибо за помощь

И тебе спасибо, узнал что аггрегат от аггрегата - экзотика. MS,PG,Access так тоже не могут. В оракле эта фишка http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions001.htm#sthref962. Может ктонить про FB сказать?

Автор: Frees 18.10.2010, 12:40
Цитата(Zloxa @  18.10.2010,  15:31 Найти цитируемый пост)
Может ктонить про FB сказать?

в FB 2.0 агрегат от агрегата - нельзя

Автор: Akina 18.10.2010, 13:05
Zloxa, экотика - это агрегатная функция без group by. Вернее, либо group by присутствует, пусть и в неявной форме (поля группировки определяются перечнем полей в остальных частях запроса), либо на выходе должна получаться 1 запись вне зависимости от входного набора данных (и 0 записей - если входной набор пуст), но не больше.
А вот если идёт агрегатка от агрегатки... при наличии групбай перечень полей группировки явно никак не подходит либо к внутренней, либо к внешней агрегатке, а при отсутствии внешний групбай к набору из максимум одной записи бессмыслен.

Автор: Zloxa 18.10.2010, 14:40
Цитата(Akina @  18.10.2010,  13:05 Найти цитируемый пост)
экотика - это агрегатная функция без group by.

ХМ. имхо это не экзотика, а вполне себе общепринятая практика.
без этого бы очень плохо жилось.

Цитата(Akina @  18.10.2010,  13:05 Найти цитируемый пост)
либо на выходе должна получаться 1 запись вне зависимости от входного набора данных (и 0 записей - если входной набор пуст), но не больше.

Есть такое правило, что при использовании аггрегата без группировки всегда возвращается одна и только одна строка. Именно по этому агрегацию без группировки нельзя представлять как аггрегацию с неявной группировкой по чему бы там ни было. Это обособленный случай. Аггрегация с группировкой, по пустому набору, вернет пустой набор. Аггрегация без группировки, по пустому набору, вернет одну запись.
Код

SQL> select nvl(max('hello'),'null') from dual where 1=2;

NVL(M
-----
null

SQL> select nvl(max('hello'),'null') from dual where 1=2 group by null;

no rows selected

MS и PG ведут себя так же

Цитата(Akina @  18.10.2010,  13:05 Найти цитируемый пост)
А вот если идёт агрегатка от агрегатки... при наличии групбай перечень полей группировки явно никак не подходит либо к внутренней, либо к внешней агрегатке, а при отсутствии внешний групбай к набору из максимум одной записи бессмыслен. 

При вложенной аггрегации, внутренний аггрегат всегда применяется к группам, а внешний - к результату внутреннего, подразумевая отсутствие группировки. Оракля не разрешает вложенные аггрегаты без груп бая. И той неоднозначности, о которой ты говоришь - нет.
Код

SQL>  select max(count(*)) from dual;
 select max(count(*)) from dual
            *
ERROR at line 1:
ORA-00978: nested group function without GROUP BY



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)