有没有办法结合这些查询?

时间:2016-08-24 14:15:11

标签: sql-server database data-processing

我已经开始将HackerRank上的一些编程问题作为一种高效的注意力分散工作"。

我正在研究SQL部分的前几个并遇到了这个问题(link):

Query the two cities in STATION with the shortest and 
longest CITY names, as well as their respective lengths 
(i.e.: number of characters in the name). If there is 
more than one smallest or largest city, choose the one 
that comes first when ordered alphabetically.

Input Format

The STATION table is described as follows:

enter image description here

where LAT_N is the northern latitude and LONG_W is 
the western longitude.

Sample Input

Let's say that CITY only has four entries: 
1. DEF
2. ABC
3. PQRS
4. WXY

Sample Output

ABC 3
PQRS 4

Explanation

When ordered alphabetically, the CITY names are listed 
as ABC, DEF, PQRS, and WXY, with the respective lengths
3, 3, 4 and 3. The longest-named city is obviously PQRS, 
but there are  options for shortest-named city; we choose 
ABC, because it comes first alphabetically.

我同意这个要求可以写得更清楚,但基本的要点很容易获得,特别是在澄清的例子中。不过,我遇到的问题是因为问题评论中的说明如下:

/*
Enter your query here.
Please append a semicolon ";" at the end of the query and 
enter your query in a single line to avoid error.
*/

现在,在单行上编写查询并不一定意味着单个查询,尽管这似乎是该语句的预期目标。但是,我能够使用以下提交通过测试用例(在2行上提交,其间带有回车符):

SELECT TOP 1 CITY, LEN(CITY) FROM STATION ORDER BY LEN(CITY), CITY;
SELECT TOP 1 CITY, LEN(CITY) FROM STATION ORDER BY LEN(CITY) DESC, CITY;

同样,这些都不是高级SQL。但它让我思考。是否有一种非常简单的方法将此输出组合到单个结果集中?我有一些想法,WHERE子句基本上在OR语句中添加了一些子查询,将两个查询合并为一个。这是我通过测试用例的另一个提交:

SELECT 
    CITY, 
    LEN(CITY) 
FROM 
    STATION 
WHERE 
    ID IN (SELECT TOP 1 ID FROM STATION ORDER BY LEN(CITY), CITY) 
OR 
    ID IN (SELECT TOP 1 ID FROM STATION ORDER BY LEN(CITY) DESC, CITY)
ORDER BY 
    LEN(CITY), CITY;

而且,是的,我意识到最终, CITY子句中的最终ORDER BY是多余的,但它有点说明这个查询并没有真正省去那么多努力,特别是不要单独返回查询结果。

注意: 这不是真正的MAX和MIN情况。鉴于以下输入,您实际上并不是第一行和最后一行:

Sample Input
1. ABC
2. ABCD
3. ZYXW

根据书面要求,您需要选择#1和#2,而不是#1和#3。

这让我觉得我的解决方案实际上可能是实现这一目标的最有效方式,但我的基于集合的思维总是可以使用一些强化,我不确定是否可能会在这里玩或不在。

6 个答案:

答案 0 :(得分:2)

也未经测试,但我没有看到它不起作用的原因:

SELECT *
FROM (
    SELECT TOP (1) CITY, LEN(CITY) AS CITY_LEN
    FROM STATION
    ORDER BY CITY_LEN, CITY
    ) AS T
UNION ALL
SELECT *
FROM (
    SELECT TOP (1) CITY, LEN(CITY) AS CITY_LEN
    FROM STATION
    ORDER BY CITY_LEN DESC, CITY
    ) AS T2;

对于每个UNION ALL语句,您不能ORDER BY SELECT,但您可以使用子查询使用TOP (1)子句和ORDER BY来解决此问题。< / p>

答案 1 :(得分:2)

这是另一种选择。我认为这很简单,很容易理解发生了什么。表现很好。

但仍然有几个子查询。

text()

答案 2 :(得分:1)

UNTESTED:

WITH CTE AS (
Select ID, len(City), row_number() over (order by City) as AlphaRN,
row_number() over (order by Len(City) desc) as LenRN) B
Select * from cte 
Where AlphaRN = 1 and (lenRN = (select max(lenRN) from cte) or 
                       lenRN = (Select min(LenRN) from cte))

答案 3 :(得分:1)

这就是我的意思。我试图只使用一个查询,没有CTE或子查询。

;WITH STATION AS ( --Dummy table
SELECT *
FROM (VALUES
(1,'DEF','EU',1,9),
(2,'ABC','EU',1,6), -- This is shortest 
(3,'PQRS','EU',1,5),
(4,'WXY','EU',1,4),
(5,'FGHA','EU',1,2),
(6,'ASDFHG','EU',1,3) --This is longest 
) as t(ID, CITY, [STATE], LAT_N,LONG_W)
)


SELECT TOP 1 WITH TIES  CITY,
                        LEN(CITY) as CITY_LEN
FROM STATION
ORDER BY ROW_NUMBER() OVER(PARTITION BY LEN(CITY) ORDER BY LEN(CITY) ASC),
        CASE WHEN MAX(LEN(CITY)) OVER (ORDER BY (SELECT NULL)) = LEN(CITY) 
                OR MIN(LEN(CITY)) OVER (ORDER BY (SELECT NULL))= LEN(CITY) 
                        THEN 0 ELSE 1 END

输出:

CITY    CITY_LEN
ABC     3
ASDFHG  6

答案 4 :(得分:1)

这是我能想到的最好的:

with Ordering as
(
    select
        City,
        Forward = row_number() over (order by len(City), City),
        Backward = row_number() over (order by len(City) desc, City)
    from
        Station
)
select City, len(City) from Ordering where 1 in (Forward, Backward);

肯定有很多方法可以解决这个问题,这可以通过各种答案来证明,但我认为在简洁明了地表达预期行为方面,任何事情都不会超过原始的双查询解决方案。有趣的问题,但是!

答案 5 :(得分:-1)

选择分钟(城市),长度(城市) 来自STATION 按长度分组(城市) 具有length(CITY)=(从STATION选择min(length(CITY)))    或length(CITY)=(从STATION选择max(length(CITY)));