Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.09.04;
Скачать: CL | DM;

Вниз

SQL-запрос для выборки данных   Найти похожие ветки 

 
serguncho ©   (2005-07-22 22:47) [0]

Добрый вечер!

Помогит разрешите проблему с запросом, пожалуйста.

Имею таблицу (tablica) c полями
NOMER_CLENA INTEGER,  
POL_CLENA   VARCHAR(1), /может быть М (мальчОнка) или F (девчОнка)/
CARD_CLENA VARCHAR(5), /пол+номер, например, F4/
RAITING FLOAT,
...

Мне нужно выбрать две самых рейтинговых дивчины и два самых-самых парня.

Думал сначала отсортировать по рейтингу и выбрать 4 души:
select first 4(*) from tablica order by RAITING

но понял ошибку, т.к. могут получиться 4 парня или 3 девушки и один парень, а никак не 50/50.

Подскажите, как организовать грамотный запрос по выборке людей (причем кол-во может быть и не пропорционально 1\1, а, например, 3 девушки- и 2 парня-лидера).


 
sniknik ©   (2005-07-22 23:45) [1]

union в файрбирде дозволяются? вот и выбирай в 2 запроса раздельно для M и Ж обьедененняя их union-ом. (чтобы не получилось в сумме 8 выбирай по 2 ;)


 
serguncho ©   (2005-07-23 09:06) [2]

Union работает. Спасибо за подсказку.
Но я чего не могу им правильно пользоваться.

select first 2 * from TABLICA where POL_CLENA="m"
union
select first 2 * from TABLICA where POL_CLENA="f"
ORDER BY 7

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


 
P.N.P. ©   (2005-07-23 09:28) [3]

>serguncho ©   (23.07.05 09:06) [2]
Как у тебя рейтинг начисляется?
Может можно сделать что-то вроде
select first 2 * from TABLICA where POL_CLENA="m"
and RAITING>
(select max(RAITING) from TABLICA where
POL_CLENA="m")-какое_то_число
union
select first 2 * from TABLICA where POL_CLENA="f"
and RAITING>
(select max(RAITING) from TABLICA where
POL_CLENA="f")-какое_то_число
ORDER BY 7


 
serguncho ©   (2005-07-23 09:52) [4]

Как у тебя рейтинг начисляется?
-------------------------------
6 вариантов - посетил:
1)5 занятий (каждый день): 100
2)4 занятия              :  80
3)3 заняти               :  60
4)2 занятия              :  40
5)1 занятие              :  20  
6)0 занятий              :   0
-------------------------------
Так что сравнивать с каким-то значением, наверное, просто так будет сложно. Особенно, если пионеры - заядлые прогульщики.
Можно, конечно, предварительно отсортировать их и в качестве параметров (для дальнейшего сравнения по Вашему коду) загнать значение 3-х парней и дам, но и тут можно получить косяк, т.к. у у 3 и 2 могут быть одинаковые значения рейтинга.


 
P.N.P. ©   (2005-07-23 10:43) [5]

А если процедуру сделать?

SET TERM ^ ;

CREATE PROCEDURE GET_RAITING (
   COUNT_M INTEGER,
   COUNT_F INTEGER,
   INACCURACY FLOAT)
RETURNS (
   NC INTEGER,
   POL VARCHAR(1),
   CARD VARCHAR(5),
   RAIT FLOAT)
AS
DECLARE VARIABLE MAX_RAITING FLOAT; /* Максимальный рейтинг */
DECLARE VARIABLE M_CNT INTEGER; /* Счетчик М */
DECLARE VARIABLE F_CNT INTEGER; /* Счетчик Ж */
begin
if (count_m<1 or count_f<1) then
   exit;
select max(raiting)-:inaccuracy from table1 into :max_raiting;
m_cnt=0;
f_cnt=0;
for select t.nomer_clena,t.pol_clena,t.card_clena,t.raiting from table1 t
  where t.raiting>=:max_raiting into :nc, :pol, :card, :rait
    do
      begin
         if (pol="M" and m_cnt<count_m) then
         begin
          m_cnt=m_cnt+1;
          suspend;
            end
         if (pol="F" and f_cnt<count_f) then
         begin
          f_cnt=f_cnt+1;
          suspend;
            end
        if (m_cnt=count_m and f_cnt=count_f) then
         exit;
      end
end
^

SET TERM ; ^

DESCRIBE PARAMETER NC PROCEDURE GET_RAITING
"Номер";
DESCRIBE PARAMETER POL PROCEDURE GET_RAITING
"Пол";
DESCRIBE PARAMETER CARD PROCEDURE GET_RAITING
"Пол+номер";
DESCRIBE PARAMETER RAIT PROCEDURE GET_RAITING
"Рейтинг";
DESCRIBE PARAMETER COUNT_M PROCEDURE GET_RAITING
"Кол-во мужчин";
DESCRIBE PARAMETER COUNT_F PROCEDURE GET_RAITING
"Кол-во женщин";
DESCRIBE PARAMETER INACCURACY PROCEDURE GET_RAITING
"Погрешность";


 
sniknik ©   (2005-07-23 11:42) [6]

почему тогда не так?
select first 2 * from TABLICA where POL_CLENA="m" ORDER BY 7
union
select first 2 * from TABLICA where POL_CLENA="f" ORDER BY 7


 
serguncho ©   (2005-07-23 11:52) [7]

sniknik © [6]
почему тогда не так?
select first 2 * from TABLICA where POL_CLENA="m" ORDER BY 7
union
select first 2 * from TABLICA where POL_CLENA="f" ORDER BY 7
---------
Ругается на такую команду.

P.N.P. ©  [5]
Спасибо. Протестирую и проинформирую о результатах. Хотя все это громоздко. Хотелось чего-то простого, как г-н sniknik написал. Не работает, увы!


 
Anatoly Podgoretsky ©   (2005-07-23 12:57) [8]

select first 2 * from TABLICA where POL_CLENA="m"
union
select first 2 * from TABLICA where POL_CLENA="f"
ORDER BY поле поле, поле рейтинг


 
Anatoly Podgoretsky ©   (2005-07-23 12:58) [9]

sniknik ©   (23.07.05 11:42) [6]
ORDER BY в ANSI SQL может применяться только для результата


 
sniknik ©   (2005-07-23 15:24) [10]

Anatoly Podgoretsky ©   (23.07.05 12:58) [9]
это я знаю (так сказать смутно догадываюсь что ограничения какието есть ;о)))
но кто сказал что файрбирд это чистый ANSI SQL? (возможно конечно, я с ним не так часто общаюсь... не в курсе тонкостей)
может и позволяет... почему не проверить.

и сказал поэтому предположительно, попробовать, был бы аксесс сказал бы точнее ;о)) там можно так
SELECT * FROM (select TOP 2 * from TABLICA where POL_CLENA="m" ORDER BY 7)
union
SELECT * FROM (select TOP 2 * from TABLICA where POL_CLENA="f" ORDER BY 7)


 
Anatoly Podgoretsky ©   (2005-07-23 15:31) [11]

sniknik ©   (23.07.05 15:24) [10]
А я именно потому и подчеркнул, ANSI, поскольку тоже не хзнаю насколько он ANSI.
Ну а по поводу применения к результату, так логично же :-)
Порядок применяется к выдаваемому набору иначе не порядок.
По вопросу видно, что надо два М и два Ж и далее по рейтингу.
Большего он не сказал, а то есть еще и более хитрые методы.


 
Nikolay M. ©   (2005-07-23 16:43) [12]


> serguncho ©

А как выбирать, если у всех рейтинг одинаковый?


 
serguncho ©   (2005-07-23 16:56) [13]

Nikolay M. ©   (23.07.05 16:43) [12]

А как выбирать, если у всех рейтинг одинаковый?
----
Не бойтесь, пиписьками меряться не будут :-))
КОнечно по алфавиту, но не столько важно, т.к. я не могу даже обычного запроса сделать.

sniknik ©   (23.07.05 15:24) [10]
и сказал поэтому предположительно, попробовать, был бы аксесс сказал бы точнее ;о)) там можно так
SELECT * FROM (select TOP 2 * from TABLICA where POL_CLENA="m" ORDER BY 7)
union
SELECT * FROM (select TOP 2 * from TABLICA where POL_CLENA="f" ORDER BY 7)
----
Не работает. Как я понял Файрберд не работает с вложенными запросами. Если кто знает, как работать - подскажите. Т.к. вл. запросы точно бы проблему решили


 
Nikolay M. ©   (2005-07-23 19:05) [14]


> serguncho ©   (23.07.05 16:56) [13]
> КОнечно по алфавиту

Что по алфавиту? Ф? И? О? И почему "конечно"?

А так ФБ поймет?
SELECT * FROM TABLICA WHERE ID IN (select TOP 2 ID from TABLICA where POL_CLENA="m" ORDER BY 7)
union
SELECT * FROM TABLICA WHERE ID IN (select TOP 2 ID from TABLICA where POL_CLENA="f" ORDER BY 7)


 
serguncho ©   (2005-07-23 19:11) [15]

Nikolay M. ©   (23.07.05 19:05) [14]
----------
Шикарно. Огромное спасибо за разрешение проблемы.


 
serguncho ©   (2005-07-23 19:13) [16]

> КОнечно по алфавиту

Что по алфавиту? Ф? И? О? И почему "конечно"?
------
В запарке некорректно отписался - по Имени М иди Ж, но это уже понятно, что вторым полем упорядочивания ставить.


 
Nikolay M. ©   (2005-07-23 19:39) [17]

Пыж. Сортировку, я еще подозреваю, надо все-таки DESC указать?


 
Deniz ©   (2005-07-25 06:35) [18]

А чем вам ответ Anatoly Podgoretsky ©   (23.07.05 12:57) [8] не нравится, или никак попробовать не получается?
select first 2 POL_CLENA, RAITING, ... from TABLICA where POL_CLENA="m"
union
select first 2 POL_CLENA, RAITING, ... from TABLICA where POL_CLENA="f"
ORDER BY 1, 2 desc, ...


 
Johnmen ©   (2005-07-25 09:15) [19]

Самый верный и простой ответ Deniz ©   (25.07.05 06:35) [18].

А ещё интересно, что такое клёна, в смысле CLENA ?
И что такое POL ?


 
Nikolay M. ©   (2005-07-25 09:56) [20]


> Deniz ©   (25.07.05 06:35) [18]
> Johnmen ©   (25.07.05 09:15) [19]

Вроде выше уже выяснили ( :о) ), что таким образом будет сортироваться результирующий набор данных, а не каждый из двух запросов по отдельности. Опять все сначала?


 
Johnmen ©   (2005-07-25 10:08) [21]

>Nikolay M. ©   (25.07.05 09:56) [20]

Будет сортировать. Так, как автору и надо, сначала девочки, потом мальчики. Если есть желание не уступать девочкам, то существует ASCENDING/DESCENDING.
На этом можно поставить точку.


 
sniknik ©   (2005-07-25 10:20) [22]

точку поставили еще в serguncho ©   (23.07.05 19:11) [15]
дальще пошол словоблуд... (тоже ничего себе занятие ;)
а автору надо не сортировать сначала девочки, потом мальчики, а TOP из 2 мальчиков и TOP двух девочек... сортировка здесь это только средство выбрать "крайних".
разница всетаки есть, выбирать сначала из М после из Ж (первых попавшихся если нет сортировки) и после сортировать, либо отсортировать каждый и выбирать по паре с максимальным рейтингом (даже если у Ж рейтинг в 3 раза ниже/выше чем у М. все одно по паре).


 
Nikolay M. ©   (2005-07-25 10:21) [23]


> Johnmen ©   (25.07.05 10:08) [21]

Блин. Ему не надо сначала девочки, а потом мальчики. Ему надо 2 топовых девочки и 2 топовых мальчика.
Оба запроса из [18] вернут по две случайных (грубо говоря) записи, т.к. в запросах не указан порядок сортировки. И только потом эти 4 записи отсортируются по полу и рейтингу. В общем случае они не будут самыми рейтинговыми.


 
Johnmen ©   (2005-07-25 10:34) [24]

Ну словоблуд, так и ладно...


 
Nikolay M. ©   (2005-07-25 10:43) [25]


> Johnmen ©   (25.07.05 10:34) [24]

Обиделся? :)


 
Johnmen ©   (2005-07-25 11:01) [26]


> Nikolay M. ©   (25.07.05 10:43) [25]


Конечно обиделся, на себя. :^)


 
Nikolay M. ©   (2005-07-25 11:04) [27]


> Johnmen ©   (25.07.05 11:01) [26]

Продыши, а то можно язву желудка заработать :)


 
Deniz ©   (2005-07-25 12:21) [28]

Согласен, фигню спорол, но для повышения производительности запроса, предлагаю к [14] добавить
SELECT first 2 * FROM TABLICA WHERE ID IN (select first 2 ID from TABLICA where POL_CLENA="m" ORDER BY 7 desc)
union
SELECT first 2 * FROM TABLICA WHERE ID IN (select first 2 ID from TABLICA where POL_CLENA="f" ORDER BY 7 desc)
вроде, как только найдется 2 мальчика, то первый запрос закончит свое выполнение, а не будет дальше перебирать оставшиеся записи, и соот-но с девочками


 
Deniz ©   (2005-07-25 12:22) [29]

... ну или ХП написать, там то все точно оптимизировать можно



Страницы: 1 вся ветка

Текущий архив: 2005.09.04;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.026 c
14-1123687195
Lamer@fools.ua
2005-08-10 19:19
2005.09.04
Поздравляю новых мастеров!


14-1121021072
Иксик
2005-07-10 22:44
2005.09.04
Предлагаю внеочередные МП


1-1124041149
leonidus
2005-08-14 21:39
2005.09.04
Подскажите программу для выявления утечки памяти


9-1115537093
grouzd[E]v
2005-05-08 11:24
2005.09.04
OpenGL - LOD feat. Renderable


8-1113240383
Eraser
2005-04-11 21:26
2005.09.04
Print Screen видео