Как найти ранг на основе роста в таблице на основе роста игроков в sql - PullRequest
0 голосов
/ 27 марта 2020

Q1: я пытался упорядочить ранг по высоте, но эта строка выглядит как недопустимая, потому что высота - это переменная, которую я пытался привести в порядок в столбце, но я не мог просто взять чтобы упорядочить, не будет ли функция ранга просто присвоить каждой высоте ранг, просто вызвав ее и выполнив переопределение, например:

CREATE OR REPLACE FUNCTION get_rank(fn VARCHAR, ln VARCHAR)  
  RETURNS FLOAT AS $$ 
  DECLARE height Float=0.0;  
  BEGIN 
  SELECT rank() OVER(PARTITION BY height) rank 
     FROM
    (
       SELECT INTO height AVG(((p.h_feet*12)+ p.h_inches)*2.54) 
       FROM Players p
     ) 
     WHERE p.firstname=fn AND p.lastname=ln; return coalesce(rank,0.0) 
END; 

$$LANGUAGE plpgsql;

Q2: Нужно ли думать об этом по-другому.

Q3: Могу ли я сделать это: PARTITION BY height ORDER BY height

Q4: Я получаю ошибку: ERROR: синтаксическая ошибка в или около "END" LINE 1: ... ERE p.firstname = fn AND p.lastname = ln; вернуть ранг END; $$ LAN ...

1 Ответ

0 голосов
/ 28 марта 2020

Я совсем не уверен, какова ваша цель, поэтому я не могу это прокомментировать. Однако ваша функция имеет несколько структурных ошибок, которые я могу. Итак, давайте посмотрим на них. Прежде всего, начиная с вашего подвыбора:

   ( 
     select into height avg(((p.h_feet*12)+ p.h_inches)*2.54) 
       from players p 
   ) 

Подвыбор может только передавать свои результаты внешнему выбору, но не может использовать предложение INTO (по крайней мере, я не могу понять, как это сделать). Но это НЕ обязательно, вы можете использовать псевдоним результата и использовать этот псевдоним во внешнем запросе. Кроме того, если бы это даже было возможно, это привело бы к ошибке времени компиляции. Необходимым форматом выбора будет «Выбрать column_list в список переменных », список переменных и список столбцов перевернуты. Наконец, Postgres требует псевдоним для подвыбора. Итак, исправляя ваши потребности:

   ( 
     select height avg(((p.h_feet*12)+ p.h_inches)*2.54) height 
       from players p 
   ) p1 

Переходя к внешнему запросу и заменяя подвыбор на результат, мы фактически получаем:

  select rank() over(partition by height) rank 
     from subselect_results
    where p.firstname=fn and p.lastname=ln; return coalesce(rank,0.0)

Что мы находим здесь:

  1. Последняя строка содержит 2 оператора, это крайне плохой процесс. Приемлемо для компилятора, но часто очень трудно найти ошибки и / или очень трудно найти исключения во время выполнения. Привыкайте к 1 оператору в строке.
  2. Оператору выбора в блоке кода требуется пропущенное здесь слово "в".
  3. Нет независимой ссылки на таблицу ни для одной таблицы. Таким образом, ЕДИНСТВЕННЫЕ доступные столбцы являются результатами подзапроса, любые ссылки на таблицы там недоступны. В этом случае единственное значение высоты. Это приводит к ошибке неопределенного столбца.
  4. "rank () over (разбиение по высоте)" в этой точке высота по существу постоянна. Ранжирование по константе всегда приводит к результату 1.
  5. Даже если вы ссылаетесь на таблицу Игроков, в которой будет указано условие where, по крайней мере, должно быть возвращено одну строку. Ранг над одной строкой всегда возвращает 1.
  6. Наконец, "return coalesce (rank, 0.0)". Ранг не определен как переменная. Это утверждение, что ошибка или неверные параметры вызывают ранг. Использование Postgres имени функции в качестве переменной является плохой практикой. Вам это может сойти с рук, но это также может привести к трудностям при поиске ошибок и / или исключений.

Исправление всего вышеперечисленного мы получаем функцию, которая будет фактически выполняться;

create or replace function get_rank(fn varchar, ln varchar) 
  returns float
  language plpgsql
as $$
declare
   rank_l float ;
begin
    select rank() over(partition by pi.height) 
         into rank_l
         from players p2
            , (
               select  avg(((p.h_feet*12)+ p.h_inches)*2.54) height
                 from players p 
              ) pi
    where p2.firstname = fn
      and p2.lastname  = ln;
    return rank_l;
end;
$$;  

Конечно, поскольку она возвращает один ряд от игроков и ранжирует константу, это может быть заменено следующим:

create or replace function get_rank(fn varchar, ln varchar) 
  returns float
  language plpgsql
as $$
begin 
   return 1.0
end;
$$; 

Хотя работая с этим, кажется, что вы спрашиваете, является рангом для конкретного игрока c, основанного только на росте. Так что, возможно, вам нужно:

-- setup 
create table players(id serial, firstname text, lastname text, h_feet integer, h_inches integer);
insert into players values (1,'A','B',6,3)
                         , (2,'C','D',6,4)
                         , (3,'E','F',6,9);

-- Build function  
create or replace function get_rank(fn text, ln text)
  returns table( firstname      text
               , lastname       text    
               , height         text
               , rank_by_height integer
               )
  language sql strict
as $$
    with player_ranking as
         (select firstname
               , lastname
               , concat(trim(to_char(h_feet, '9')), '''', trim(to_char(h_inches,'00')),  '"') size
               , 12*h_feet + h_inches height
            from players
         )
    select firstname, lastname, size, rnk
      from (
            select firstname, lastname, size, rank() over (order by height desc)::integer rnk
              from player_ranking pr
           ) pr
     where firstname = fn
       and lastname  = ln;
$$;

-- test 
select * 
  from  get_rank('C','D');  

Я оставлю вам возможность исследовать, что делает каждая используемая функция, и разницу между sql и pgpl sql функциями. Учиться / изучать, чтобы понять, никогда не бывает в талии времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...