首页 > 解决方案 > 在不使用 TOP 的情况下为 SSMS 选择 Last Row Hackerrank 挑战者

问题描述

这是hackerrank.com上的以下问题:

………………………………………………………………………………

用最短和最长的CITY名称查询STATION中的两个城市,以及它们各自的长度(即:名称中的字符数)。如果有多个最小或最大的城市,请选择按字母顺序排列的第一个城市。

输入格式

STATION表描述如下:

字段 - 类型:id - 数字,城市 - varchar(21),州 - varchar(2),lat_n - 数字,long_w - 数字

其中 LAT_N 是北纬,LONG_W 是西经。

样本输入

假设 CITY 只有四个条目:DEF、ABC、PQRS 和 WXY

样本输出

ABC 3 PQRS 4 解释

按字母顺序排列时,CITY 名称列为 ABC、DEF、PQRS 和 WXY,其长度分别为 和 。名字最长的城市显然是PQRS,但是最短名字的城市有选项;我们选择 ABC,因为它按字母顺序排在第一位。

注意您可以编写两个单独的查询来获得所需的输出。它不必是单个查询。

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

我想用 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;

但它给出了错误:

你的输出(标准输出)

阿莫 3

李 3

罗伊 3

圣克罗伊 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)

阿莫 3

圣克罗伊 21 号海洋酒店

更改代码解决了重复长度为 3 的问题,因为我知道第一行号。但是,如果我试图在不知道数字是什么的情况下获取最后一行编号,就会出现问题。我在 SSMS 上找到最后一行的所有其他帖子都涉及使用 TOP,但正如您所见,TOP 只会检索一行,但我的答案需要 2 个,因为我试图在 1 个查询中解决 2 个查询问题。

基本上,我解决了查询,但我想知道如果有 2 个城市的长度为 21,你怎么能做到这一点。在这种情况下,我如何找到最后一行?

非常感谢您的时间。

标签: sqlsql-serverssms

解决方案


你似乎就在那里——了解如何row_number()运作。你只需要使用它两次。你想要的逻辑是:

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

推荐阅读