【问题标题】:SQL query for finding the longest name and shortest name in a table用于查找表中最长名称和最短名称的 SQL 查询
【发布时间】:2016-02-14 20:11:31
【问题描述】:

我有一张表,其中一列是 varchar(city) 类型。并希望找到存储在该列中的最长和最短的值。

select a.city, a.city_length from (select city, char_length(city) city_length 
from station order by city, city_length) a
where a.city_length = (select min(a.city_length) from a) or
      a.city_length = (select max(a.city_length) from a)
group by a.city_length;

有人可以帮忙吗?谢谢


一种解决方案:

select * from (select city, char_length(city) city_length from station order by city, city_length) a group by a.city_length order by a.city_length limit 1;
select * from (select city, char_length(city) city_length from station order by city, city_length) a group by a.city_length order by a.city_length desc limit 1;

【问题讨论】:

  • 您在哪个 RDBMS 上工作?了解这一点很重要,因为我们将能够使用更高效的 rdbms 特定功能(并为您提供一些有关高级技术的提示)
  • 请注意,可能没有“最长”的名字,这意味着您可能有多个。

标签: sql


【解决方案1】:

我认为我们不需要使用 Min 和 Max 函数,也不需要 Group by。

我们可以使用下面的代码来实现:

select top 1 City, LEN(City) City_Length from STATION order by City_Length ASC,City ASC

select top 1 CITY, LEN(city) City_Length from station order by City_Length desc, City ASC

但在这种情况下,它会在 2 个表中显示输出,如果我们想在一个表中合并,那么我们可以使用 Union 或 Union ALL。下面是相同的 SQL 查询

  select * from (
     select top 1 City, LEN(City) City_Length from STATION order by City_Length ASC,City ASC) TblMin
   UNION
   select * from (
   select top 1 CITY, LEN(city) City_Length from STATION order by City_Length desc, City ASC) TblMax

这里我将 select 语句嵌套在子查询中,因为当我们使用 order by 子句时,我们不能直接使用 Union 或 Union ALL,这就是我将它写在子查询中的原因。 p>

【讨论】:

  • oracle 错误弹出为ERROR at line 1: ORA-00904: "TOP": invalid identifier
  • 对未指定 dbms 的问题的产品特定答案。至少告诉我们这是用于哪个 dbms。
  • @jarlh 适用于 SQL Server。
【解决方案2】:

最短的:

select TOP 1 CITY,LEN(CITY) LengthOfCity FROM STATION ORDER BY LengthOfCity ASC, CITY ASC;

最长:

select TOP 1 CITY,LEN(CITY) LengthOfCity FROM STATION ORDER BY LengthOfCity DESC, CITY ASC;

这适用于 HackerRank 挑战问题(MS SQL Server)。

【讨论】:

  • 如果我们选择Oracle,那么这个查询在黑客等级中不起作用。它抛出错误,因为`error is ERROR at line 1: ORA-00904: "TOP": invalid identifier`
  • 此查询适用于 MS SQL Server,不适用于 oracle。试试这个oracle:最短:select * from (select CITY,LENGTH(CITY) LengthOfCity FROM STATION ORDER BY LengthOfCity ASC, CITY ASC) where rownum = 1;最长:select * from (select CITY,LENGTH(CITY) LengthOfCity FROM STATION ORDER BY LengthOfCity DESC, CITY ASC) where rownum = 1;
  • 对于 MySql: SELECT CITY, LENGTH(CITY) as LEN FROM STATION ORDER BY LEN ASC, CITY ASC LIMIT 1; SELECT CITY, LENGTH(CITY) as LEN FROM STATION ORDER BY LEN DESC, CITY ASC LIMIT 1;
  • 什么是 LengthOfCity ... 是否类似于 alias ... 在黑客排名中没有列名称为 LengthOfCity
  • @ShubhamJain 你说得对,它是别名,定义为稍后在 ORDER 中使用。
【解决方案3】:

在 MySQL 中

(select city, LENGTH(city) cityLength  from station order by cityLength desc,city asc LIMIT 1)
    union all
    (select city, LENGTH(city) cityLength  from station order by cityLength asc,city asc LIMIT 1)

【讨论】:

  • 为什么限制 1 ?能否请您解释一下?
  • @Taylor,LIMIT 1 将查询的输出减少到一个条目(在本例中为城市)。通过查询,您可以获得城市名称最短和最长的城市。
【解决方案4】:

也许是一个更简单的选择,因为我想您正在寻求解决黑客等级问题的帮助?添加限制使我更容易调试返回错误的问题所在。

SELECT city, length(city) FROM station order by length(city) desc limit 1;

SELECT city, length(city) FROM station order by length(city) asc, city asc limit 1

【讨论】:

    【解决方案5】:

    您的查询只需要一些调整。根本问题是您不能在子查询中使用a,因为您正在这样做:

    select a.city, a.city_length
    from (select city, char_length(city) city_length 
          from station 
         ) a
    where a.city_length = (select min(char_length(city)) from station) or
          a.city_length = (select max(char_length(city)) from station);
    

    也就是说,编写查询的更简单方法是:

    select s.*
    from station s cross join
         (select min(char_length(city)) as mincl, max(char_length(city)) as maxcl
          from station
         ) ss
    where char_length(s.city) in (mincl, maxcl);
    

    【讨论】:

      【解决方案6】:

      在甲骨文中:

      select * from (select city, min(length(city)) minl from station group by city order by minl, city) where rownum = 1;
      select * from (select city, max(length(city)) maxl from station group by city order by maxl desc, city) where rownum = 1;

      【讨论】:

        【解决方案7】:

        升序:

        SELECT city, CHAR_LENGTH(city) FROM station ORDER BY CHAR_LENGTH(city), city LIMIT 1;

        降序:

        SELECT city, CHAR_LENGTH(city) FROM station ORDER BY CHAR_LENGTH(city) DESC, city LIMIT 1;

        【讨论】:

          【解决方案8】:

          这是一种使用 CTE 的方法。首先它找到最长和最短的,而不是匹配的城市:

          DECLARE @tbl TABLE(CityName VARCHAR(100));
          INSERT INTO @tbl VALUES ('xy'),('Long name'),('very long name'),('middle'),('extremely long name');
          
          WITH MyCTE AS 
          (
              SELECT MAX(LEN(CityName)) AS Longest
                    ,MIN(LEN(CityName)) AS Shortest
              FROM @tbl
          )
          SELECT * 
          FROM MyCTE
          --You must think about the chance of more than one city matching the given length
          CROSS APPLY(SELECT TOP 1 CityName FROM @tbl WHERE LEN(CityName)=Longest) AS LongestCity(LongName)
          CROSS APPLY(SELECT TOP 1 CityName FROM @tbl WHERE LEN(CityName)=Shortest) AS ShortestCity(ShortName)
          

          结果

          Longest Shortest    LongName               ShortName
          19       2          extremely long name    xy
          

          【讨论】:

            【解决方案9】:

            首先找到city 的最短长度,并与city 的最长长度进行联合。这最大限度地降低了查询的复杂性。

            (select city, char_length(city) as len_city
            from station
            order by len_city limit 1)
            union ( select city, char_length(city) as len_city
                from station
                order by len_city desc limit 1) 
            order by len_city
            

            【讨论】:

              【解决方案10】:
              select top(1) city, max(len(city)) [Length] from station group by city order by [Length]
              select top(1) city, max(len(city)) [Length] from station group by city order by [Length] DESC
              

              在 SQL Server 2016 中测试

              【讨论】:

                【解决方案11】:

                我在 SQL Server 中使用 CTE 和 dense_rank 函数完成了这项工作。 排名如何运作?

                长度上的第一个分区(形成组),即相同的长度构成一个组(分区)。然后在每个分区中按字母顺序排列所有名称。然后在每个分区内分配等级(dRank 列)。因此,每个组中的排名 1 将分配给按字母顺序出现在其各自分区中的第一个名称。所有这些都发生在公用表表达式(cte 块)中

                "with cte as
                (
                select *, LEN(city) as length, DENSE_RANK() over (partition by len(city) order by city) as dRank from Station
                )"
                
                select city,length from cte where dRank = 1 and length = (select MIN(length) from cte)
                UNION
                select city,length from cte where dRank = 1 and length = (select max(length) from cte)"
                

                【讨论】:

                  【解决方案12】:

                  我使用 Oracle 的 WITH 子句将最短/最长的名称保存在临时变量中,而不是在主“from”子句中进行查询。 SQL WITH clause example

                  WITH shortnames AS
                  (SELECT city, length(city) 
                   FROM station 
                   ORDER BY length(city) asc, city),
                  
                   longnames AS
                   (SELECT city, length(city) 
                    FROM station
                    ORDER BY length(city) desc, city)
                  
                  SELECT * FROM shortnames WHERE ROWNUM=1
                  UNION ALL
                  SELECT * FROM longnames WHERE ROWNUM=1;
                  

                  【讨论】:

                    【解决方案13】:

                    这是在 MySQL 中执行此操作的另一种方式。可能不是最好的,但仍然是逻辑上正确的选择。

                    select
                       city,
                       length(city) 
                    from
                       station 
                    where
                       length(city) in 
                       (
                          select
                             max(length(city)) 
                          from
                             station 
                          union
                          select
                             min(length(city)) 
                          from
                             station
                       )
                    order by
                       length(city) desc,
                       city asc limit 2;
                    

                    【讨论】:

                      【解决方案14】:

                      在 Oracle(以及任何其他支持分析函数的语言)中,使用ROW_NUMBER 分析函数,您可以根据城市的ASCending(或DESCending)长度为行分配一个唯一编号。由于可能有多个具有相同长度的行,因此可以应用二级顺序来按字母顺序获取该长度的第一个城市。那么您只需要一个外部查询来将结果过滤为最短(或最长)的名称:

                      SELECT city
                      FROM   (
                        SELECT CITY,
                               ROW_NUMBER() OVER ( ORDER BY LENGTH( CITY ) ASC,  CITY ) shortest_rn,
                               ROW_NUMBER() OVER ( ORDER BY LENGTH( CITY ) DESC, CITY ) longest_rn
                        FROM   station
                      )
                      WHERE shortest_rn = 1
                      OR    longest_rn  = 1;
                      

                      如果您想返回所有名称最短(或最长)的城市,请使用DENSE_RANK 而不是ROW_NUMBER

                      SELECT city
                      FROM   (
                        SELECT CITY,
                               DENSE_RANK() OVER ( ORDER BY LENGTH( CITY ) ASC  ) shortest_rn,
                               DENSE_RANK() OVER ( ORDER BY LENGTH( CITY ) DESC ) longest_rn
                        FROM   station
                      )
                      WHERE shortest_rn = 1
                      OR    longest_rn  = 1
                      ORDER BY shortest_rn, city; -- Shortest first and order tied lengths alphabetically
                      

                      【讨论】:

                        【解决方案15】:

                        在 Oracle 12c 中,这可以使用 FETCH..FIRST 完成

                        最短的

                        select * FROM station ORDER BY LENGTH(city) DESC FETCH FIRST 1 ROWS ONLY;
                        

                        最长

                        select * FROM station ORDER BY LENGTH(city) ASC FETCH FIRST 1 ROWS ONLY;
                        

                        【讨论】:

                          【解决方案16】:

                          对于甲骨文:

                          select min(city),length(city) from station where length(city) <= all(select 
                          length(city) from station) group by length(city);
                          
                          select max(city),length(city) from station where length(city) >= all(select 
                          length(city) from station) group by length(city);
                          

                          【讨论】:

                            【解决方案17】:

                            以下查询似乎很简单:

                            select 
                                city, leng 
                            from
                                (select top 1 
                                     city, len(city) leng 
                                 from 
                                     station 
                                 where 
                                     len(city) = (select min(len(city)) from station) 
                                 order by 
                                     city
                            
                                 Union all
                            
                                 select top 1 
                                     city, len(city) leng 
                                 from 
                                     station 
                                 where 
                                     len(city) = (select max(len(city)) from station)  
                                 order by 
                                     city) result;
                            

                            里面的第一个查询返回最小长度的城市,而第二个查询返回最大长度的城市。

                            希望这会有所帮助。

                            【讨论】:

                              【解决方案18】:

                              城市的最短名称:

                              SELECT ST.CITY,LENGTH(ST.CITY) AS LENGTH FROM STATION ST
                              ORDER BY LENGTH ASC, ST.CITY ASC
                              LIMIT 1;
                              

                              最长城市名:

                              SELECT ST.CITY,LENGTH(ST.CITY) AS LENGTH FROM STATION ST
                              ORDER BY LENGTH DESC, ST.CITY DESC
                              LIMIT 1;
                              

                              【讨论】:

                                【解决方案19】:

                                在 Oracle 中是这样的,

                                SELECT CITY,LENGTH(CITY) FROM   (SELECT MIN(CITY) CITY  FROM STATION WHERE LENGTH(CITY)=(SELECT MIN(LENGTH(CITY)) FROM STATION))
                                UNION ALL
                                SELECT CITY,LENGTH(CITY) FROM   (SELECT MAX(CITY) CITY  FROM STATION WHERE LENGTH(CITY)=(SELECT MAX(LENGTH(CITY)) FROM STATION));    
                                

                                【讨论】:

                                  【解决方案20】:

                                  此查询将在您的条件下运行良好,这两个查询完全相同。在第一个查询中,我们只是按降序对记录进行排序以获取长度最大的城市名称,在第二部分中,我们只是按升序获取记录以获取具有最小长度的城市,所有其余查询都是相同的。亲们看看吧。

                                  详情:

                                  1. 选择语句取出记录
                                  2. 使用 group by 子句,因为我使用的是 Len() 聚合函数。
                                  3. 将所有检索到的记录按降序和升序排序,得到前1名,取最大最小长度城市。

                                    select  Top 1  City,max(len(City)) as Length  
                                    from STATION 
                                    group by City 
                                    ORDER BY Length desc 
                                    
                                    select  Top 1  City,max(len(City)) as Length  
                                    from STATION 
                                    group by City 
                                    ORDER BY Length ASC
                                    

                                  【讨论】:

                                    【解决方案21】:

                                    对于一个结果表中的 oracle SQL。这将检索最小和最大城市名称,如果长度相同,则第一个城市将按字母顺序排序。

                                    SELECT * FROM (
                                        SELECT CITY, LENGTH(CITY) CITY_LENGTH 
                                        FROM STATION 
                                        ORDER BY CITY_LENGTH ASC, CITY ASC ) MAX_LEN  
                                    WHERE ROWNUM <= 1
                                    UNION
                                    SELECT * FROM (
                                        SELECT CITY, LENGTH(CITY) CITY_LENGTH 
                                        FROM STATION 
                                        ORDER BY  CITY_LENGTH DESC, CITY ASC ) MIN_LENGTH  
                                    WHERE ROWNUM <= 1;
                                    

                                    【讨论】:

                                      【解决方案22】:

                                      select city,length(city) from (select city,length(city),rank() over(partition by length(city) order by length(city),city asc) as rnk from station)a where a. rnk=1;

                                      【讨论】:

                                        【解决方案23】:

                                        Oracle中,我们可以这样做

                                        select city, length(city)
                                        from (select city from STATION order by length(city) DESC, city ASC)
                                        where rownum = 1 
                                        union
                                        select city, length(city)  
                                        from (select city from STATION order by length(city), city ASC)
                                        where rownum = 1;
                                        

                                        我们的想法是获得最长和最短的城市,然后将它们合并为一个结果。

                                        【讨论】:

                                          【解决方案24】:
                                          SELECT MAX(LENGTH(transaction_id)) AS Longest ,MIN(LENGTH(transaction_id)) AS Shortest FROM cards
                                          

                                          【讨论】:

                                            【解决方案25】:

                                            length(CITY) 将返回字符串的长度,

                                            https://www.w3schools.com/sql/func_mysql_length.asp

                                            (select CITY, length(CITY) from STATION order by length(CITY),CITY limit 1)
                                            UNION
                                            (select CITY, length(CITY) from STATION order by length(CITY) DESC limit 1);
                                            

                                            【讨论】:

                                              【解决方案26】:

                                              对于 Oracle,这对我有用(HackerRank)

                                              --shortest 
                                              SELECT CITY,L FROM 
                                              (select CITY,length(CITY) L
                                              from STATION   
                                              order by length(CITY) ASC, CITY ASC)
                                              WHERE ROWNUM=1
                                              UNION ALL 
                                              --longest 
                                              SELECT CITY,L FROM 
                                              (select CITY,length(CITY) L
                                              from STATION   
                                              order by length(CITY) DESC, CITY ASC)
                                              WHERE ROWNUM=1;
                                              

                                              原文原文 我尝试了很多方法,但这项工作,我按长度排序,然后按字母顺序,最后只得到第一行。

                                              【讨论】:

                                                【解决方案27】:

                                                这适用于mysql

                                                -- smallest
                                                SELECT city, length(city) FROM station 
                                                WHERE length(city) = (select min(length(city)) from station)
                                                ORDER BY city
                                                limit 1;
                                                
                                                -- largest
                                                SELECT city, length(city) FROM station 
                                                WHERE length(city) = (select max(length(city)) from station)
                                                ORDER BY city
                                                limit 1;
                                                

                                                【讨论】:

                                                  【解决方案28】:

                                                  这里有一个严格使用 MIN 和 MAX 的解决方案

                                                  这里的概念是将MIN 应用于城市名称的长度。在这些结果中,再次将MIN 应用于城市名称​​本身,以按字母顺序查找第一个。

                                                  当然,同样使用MAX求最大城市长度,对两个查询进行一次UNION求最终解。

                                                  无需排序,ASCDESCLIMITORDER BY

                                                  很好的参考: https://www.zentut.com/sql-tutorial/sql-min-max/

                                                  (
                                                      SELECT s3.CITY, s3.Len 
                                                      FROM (
                                                          SELECT CITY, s1.Len
                                                          FROM (
                                                              SELECT CITY, LENGTH(CITY) AS Len
                                                              FROM STATION
                                                          ) s1
                                                          WHERE
                                                              s1.Len = (
                                                                  SELECT MIN(s2.Len2)
                                                                  FROM (
                                                                      SELECT LENGTH(CITY) AS Len2
                                                                      FROM STATION
                                                                  ) s2
                                                              )
                                                          ) s3
                                                      WHERE
                                                          s3.CITY = (
                                                              SELECT MIN(CITY)
                                                              FROM STATION
                                                              WHERE s3.Len = LENGTH(CITY)
                                                          )
                                                  ) UNION (
                                                      SELECT s3.CITY, s3.Len 
                                                      FROM (
                                                          SELECT CITY, s1.Len
                                                          FROM (
                                                              SELECT CITY, LENGTH(CITY) AS Len
                                                              FROM STATION
                                                          ) s1
                                                          WHERE
                                                              s1.Len = (
                                                                  SELECT MAX(s2.Len2)
                                                                  FROM (
                                                                      SELECT LENGTH(CITY) AS Len2
                                                                      FROM STATION
                                                                  ) s2
                                                              )
                                                          ) s3
                                                      WHERE
                                                          s3.CITY = (
                                                              SELECT MIN(CITY)
                                                              FROM STATION
                                                              WHERE s3.Len = LENGTH(CITY)
                                                          )
                                                  );
                                                  

                                                  【讨论】:

                                                    【解决方案29】:
                                                    with cte (rank, city , CityLength) 
                                                    As 
                                                    (select  dense_rank() over (partition by len(city) order by city asc) as Rank, city, len(city) 
                                                        from station 
                                                    where len(city) in 
                                                        ((select max(len(city)) from station) 
                                                        union (select min(len(city)) from station)))
                                                    select city,citylength from cte where rank = 1;
                                                    

                                                    【讨论】:

                                                    • 欢迎来到 Stack Overflow!虽然此代码 sn-p 可以解决问题,包括解释 really helps 以提高您的帖子质量。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人!请edit您的答案添加解释,并说明适用的限制和假设。
                                                    【解决方案30】:
                                                    select * from (select city,length(city)from station group by city having length(city) in ((select min(length(city))from station))order by city) where rownum<2
                                                    UNION
                                                    select * from (select city,length(city)from station group by city having length(city) in ((select max(length(city))from station))order by city) where rownum<2;
                                                    

                                                    【讨论】:

                                                    • 请对此作出一些解释。
                                                    猜你喜欢
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    • 2022-10-15
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    相关资源
                                                    最近更新 更多