Как использовать псевдоним с разделом в SQL - PullRequest
0 голосов
/ 07 января 2019

Я получаю записи игроков, которые были отнесены к категории гандикапов гольфа. Как игроки с гандикапом от 0 до 5 лежат в диапазоне 0-5 и аналогично, гандикап между 6-11 лежит в диапазоне 6-11 и так далее и так далее. Я пытаюсь собрать 3 лучших игроков из каждого диапазона, чтобы я мог настроить полеты для каждого раунда.

Я использовал разделение по пунктам для разделения записей и ROW_NUMBER для получения трех лучших игроков из каждого диапазона. Чтобы определить диапазоны, я использовал несколько случаев. Теперь, как я могу использовать диапазон в качестве псевдонима с разделением или любым другим способом, который может генерировать правильный результат. Ниже мой запрос.

  select * from (
  select  uu.Id, firstname, lastname, userhandicap, 
  case when userhandicap>=0 and userhandicap<=5 then '0-5'
  when userhandicap>=6 and userhandicap<=11 then '6-11' 
  when UserHandicap>=12 and UserHandicap<=18 then '12-18' 
  when UserHandicap>=19 and UserHandicap<=26 then '19-26'
  else '27 and above' end as range, RN = ROW_Number()  over (PARTITION BY 
  range order by cast(userhandicap as int))
  from dbo.[User] uu inner join dbo.[EventRegisteredUsers] eru
  on uu.Id = eru.UserId 
  where eru.UserId not in (Select fp.UserId from dbo.[FlightPlayer] fp 
  inner join dbo.[Flight] f
  on fp.FlightId = f.Id 
  where f.Rounds = '1'
  and f.Starthole = '0a9b926e-0baa-4369-8cf8-8fc84ca80d65' and f.EventId = 
  '7de10ad6-098d-419f-9c2d-2e62803ad1f7')
  and eru.EventId = '7de10ad6-098d-419f-9c2d-2e62803ad1f7') uu
  WHERE 
   uu.RN <= 3 

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Вы можете использовать apply для определения значения range в пределах подзапроса. Это самый простой метод определения диапазона:

select *
from (select uu.Id, firstname, lastname, userhandicap, 
             row_number() over (partition by v.range order by cast(userhandicap as int)) as seqnum
      from dbo.[User] uu inner join
           dbo.[EventRegisteredUsers] eru
           on uu.Id = eru.UserId cross apply
           (values (case when userhandicap <= 5 then '0-5'
                         when userhandicap <= 11 then '6-11' 
                         when UserHandicap <= 18 then '12-18' 
                         when UserHandicap <= 26 then '19-26'
                         else '27 and above'
                    end)
           ) v(range)
      where not exists (select 1
                        from dbo.[FlightPlayer] fp join
                             dbo.[Flight] f
                             on fp.FlightId = f.Id 
                        where eru.UserId = fp.UserId and 
                              f.Rounds = '1' and
                              f.Starthole = '0a9b926e-0baa-4369-8cf8-8fc84ca80d65' and
                              f.EventId = '7de10ad6-098d-419f-9c2d-2e62803ad1f7'
                       ) and
            eru.EventId = '7de10ad6-098d-419f-9c2d-2e62803ad1f7'
       ) uu
where uu.seqnum <= 3; 

Обратите внимание на другие изменения в запросе:

  • Не используйте not in с подзапросом. Если подзапрос возвращает значение NULL, то все значения отфильтровываются. Это не (обычно) ожидаемое поведение.
  • Выражение case слишком сложное. Используйте тот факт, что case гарантированно оценивает условия по порядку.
  • Вы должны указать все имена столбцов в запросе, который содержит более одного запроса. Однако неясно, откуда берутся колонны.
  • Предположительно handicap никогда не бывает отрицательным, основываясь на вашей оригинальной логике (и правилах игры в гольф), поэтому мне удобно снять это условие.
0 голосов
/ 07 января 2019

используйте cte

with cte as
(
select  uu.Id, firstname, lastname, userhandicap, 
  case when userhandicap>=0 and userhandicap<=5 then '0-5'
  when userhandicap>=6 and userhandicap<=11 then '6-11' 
  when UserHandicap>=12 and UserHandicap<=18 then '12-18' 
  when UserHandicap>=19 and UserHandicap<=26 then '19-26'
  else '27 and above' end as range
  from dbo.[User] uu inner join dbo.[EventRegisteredUsers] eru
  on uu.Id = eru.UserId 
  where eru.UserId not in (Select fp.UserId from dbo.[FlightPlayer] fp 
  inner join dbo.[Flight] f
  on fp.FlightId = f.Id 
  where f.Rounds = '1'
  and f.Starthole = '0a9b926e-0baa-4369-8cf8-8fc84ca80d65' and f.EventId = 
  '7de10ad6-098d-419f-9c2d-2e62803ad1f7')
  and eru.EventId = '7de10ad6-098d-419f-9c2d-2e62803ad1f7'
), t2 as 
(
 select *,row_number() over(partition by range order by cast(userhandicap as int) rn from cte
) select * from t2 where rn<=3
...