ВЫБЕРИТЕ Претендента Last Row Hackerrank для SSMS без использования TOP - PullRequest
1 голос
/ 08 мая 2020

Вот следующий вопрос на hackerrank.com:

........................

Запросить два города в STATION с самым коротким и самым длинным названием CITY, а также их длина (например, количество символов в названии). Если существует более одного самого маленького или большого города, выберите тот, который будет первым в алфавитном порядке.

Формат ввода

Таблица STATION описывается следующим образом:

поле - тип: id - число, город - varchar (21), состояние - varchar (2), lat_n - число, long_w - число

, где LAT_N - северная широта, а LONG_W - западная долгота.

Пример ввода

Предположим, что CITY имеет только четыре записи: DEF, AB C, PQRS и WXY

Пример вывода

AB C 3 PQRS 4 Пояснение

В алфавитном порядке названия CITY отображаются как AB C, DEF, PQRS и WXY с соответствующими длинами и. Город с самым длинным названием, очевидно, - это PQRS, но есть варианты для города с самым коротким названием; мы выбираем AB C, потому что он идет первым по алфавиту.

Примечание. Вы можете написать два отдельных запроса, чтобы получить желаемый результат. Это не обязательно должен быть один запрос.

.................................... .............

Я хотел решить это с помощью 1 запроса, поэтому я использовал CTE:

    with cte as(
                SELECT  City,
                        LEN (City)     as l,
                        MAX (LEN (City)) over() as x,
                        MIN (LEN (City)) OVER() as m,
 --                       ROW_NUMBER() OVER(ORDER BY LEN(city),city) AS r
                FROM    Station

                )
    SELECT  city,
            l
    FROM    cte
    WHERE   l = x  OR l = m
    --WHERE   l = x  OR r = 1
    ORDER BY L, city;

, но он дает ошибку:

Ваш вывод (стандартный вывод)

Amo 3

Lee 3

Roy 3

Marine On Saint Croix 21

потому что должно быть только 2 города, один с длиной 3, а другой с длиной 21. Поэтому я изменил код как таковой: (обратите внимание на изменения в коде Rem'd out)

    with cte as(
                SELECT  City,
                        LEN (City)     as l,
                        MAX (LEN (City)) over() as x,
--                        MIN (LEN (City)) OVER() as m,
                        ROW_NUMBER() OVER(ORDER BY LEN(city),city) AS r
                FROM    Station

                )
    SELECT  city,
            l
    FROM    cte
--    WHERE   l = x  OR l = m
    WHERE   l = x  OR r = 1
    ORDER BY L, city;

Это верно, вывод выглядит следующим образом: Ваш вывод (stdout)

Amo 3

Marine On Saint Croix 21

Изменение кода решило проблему дублирования длины 3 проблема, поскольку я знал номер первой строки. Но мои проблемы возникали, если я пытался получить номер последней строки, не зная, какой это был номер. В каждом другом сообщении, которое я видел для поиска последней строки в SSMS, используется TOP, но, как вы можете видеть, TOP будет извлекать только одну строку, но мне нужно 2 для моего ответа, поскольку я пытаюсь решить 2 вопроса запроса в 1 запросе.

По сути, я решил запрос, но хотел бы знать, как вы могли бы это сделать, если бы было 2 города длиной 21. Как мне найти последнюю строку в этой ситуации?

Большое спасибо за ваше время.

Ответы [ 2 ]

0 голосов
/ 08 мая 2020

Подход cte также может работать, если выбрать группу min (city) по len (city):

WITH cte AS
(
SELECT  
    LEN(City) AS l,
    MIN(City) AS city,
    MAX(LEN (City)) OVER() AS maxlen,
    MIN(LEN (City)) OVER() AS minlen
FROM  (VALUES('abc'), ('klm'), ('xyz'), ('bcde'), ('cdef'), ('bcdef'), ('cdefg'), ('pqrstu'), ('aqrstu')) AS Station(City) --Station
GROUP BY LEN(City)
)
SELECT  city,
        l
FROM    cte
WHERE   l = maxlen  OR l = minlen
ORDER BY l, city;
0 голосов
/ 08 мая 2020

Кажется, вы там - понимаете, как работает row_number(). Вам просто нужно использовать его дважды. Вам нужен logi c:

WITH cte AS (
      SELECT City,LEN (City) as l,
             ROW_NUMBER() OVER (ORDER BY LEN(city), city) AS seqnum_min,
             ROW_NUMBER() OVER (ORDER BY LEN(city) DESC, city) AS seqnum_max
      FROM Station
     )
SELECT city, l
FROM cte
WHERE 1 IN (seqnum_min, seqnum_max)
ORDER BY L, city;

Используя TOP, вы, вероятно, будете использовать UNION ALL:

select *
from ((select top (1) s.*
       from station s
       order by len(city), city
      ) union all
      (select top (1) s.*
       from station s
       order by len(city) desc, city
      ) 
     ) s
...